Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >【一起学Python】STEAM游戏评测爬虫

【一起学Python】STEAM游戏评测爬虫

作者头像
不二小段
发布于 2018-04-08 03:45:30
发布于 2018-04-08 03:45:30
9.4K59
代码可运行
举报
文章被收录于专栏:不二小段不二小段
运行总次数:9
代码可运行

别催更,越催越懒得写。催更只接受赞赏…可惜我的微信还没有赞赏的功能…

今天刚接的需求&新鲜的代码…

有个大佬昨天跟我说

来给我爬一下Steam的游戏评测吧,我要这个数据,这个数据,还有这个数据。效率我不管,存储方式我不管,数据分析我不管,你爬好了跟我说。

于是就有了今天的文章。

闲话少叙,我挑核心的部分来记录今天的工作。 主线任务:给定某STEAM平台游戏,抓取其评测相关信息(包括但不限于upvote/downvote、昵称、时间、评论等) 支线任务:抓取评价用户的游戏库存 隐藏任务:对用户评论进行情感语义分析,并对比其推荐/不推荐分析语义和评价的相关性

这篇文章里我们的目标是完成主线和隐藏任务,支线任务之后再写一篇。

第一步,确定需求和入口

需求前面已经给定了,那么确定我们抓取的入口,也就是网页链接。 以最近颇具争议的游戏 H1Z1 为例。打开其STEAM商店页面: http://store.steampowered.com/app/433850/ 在页面最下方找到“浏览所有评测”,获取入口链接: http://steamcommunity.com/app/433850/reviews/?browsefilter=toprated&snr=15_reviews

第二步,使用Python模拟请求,获得页面源码

使用firebug(或者Chrome的F12)抓网络请求。

发现只有三个请求,下面三个都Google Analytics的统计脚本,也就是说我们要抓取的内容必然在第一个请求里。 使用Python构造网络请求,并打印源码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests
url = ‘http://steamcommunity.com/app/433850/reviews/?browsefilter=toprated&snr=15_reviews‘ 
html = requests.get(url).text
print(html)

打印出来的源代码太长了,就不再展示了。

第三步,parse&extract 从页面源码中提取内容

获取到页面源码后,我们需要从繁杂的源代码中提取出我们需要的内容。我们可以通过审查元素迅速定位内容所在的标签。

定位到比较清晰的标签后,推荐通过BeautifulSoup直接进行提取。 当然这里有一个小小的隐藏知识,如果你直接查看这个请求的HTML的话,会发现里面并没有直接展示出评测内容。也就是说评测内容其实是在页面加载的过程中由JS渲染完成的。

在有些网站的处理中,会将JS和需要渲染的内容分为两次请求发送。 这次的处理没有那么复杂,如果有人根本没发现JS渲染这一步而直接去解析页面源码的话,也是没有问题的。 下面我们使用BeautifulSoup进行相应的标签定位和解析,我就不赘述过程了。只要定位到相应标签,然后直接使用soup.find()就可以了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')  # 如果装了lxml,推荐把解析器改为lxml
reviews = soup.find_all('div', {'class': 'apphub_Card'})
for review in reviews:
    nick = review.find('div', {'class': 'apphub_CardContentAuthorName'})
    title = review.find('div', {'class': 'title'}).text
    hour = review.find('div', {'class': 'hours'}).text.split(' ')[0]
    link = nick.find('a').attrs['href']
    comment = review.find('div', {'class': 'apphub_CardTextContent'}).text
    print(nick.text, title, hour, link, )
    print(comment.split('\n')[3].strip('\t'))

这样我们就能将需要的信息提取并一一打印出来了。但是这时候我们又发现了另一个问题,为什么这边打印出来的全都是英文,而且跟我们在网页上看到的评测也不一样啊。原因其实是我们浏览器存了cookies,而且默认的语言是简体中文和英语,所以会把中文评测放在前面。 那么如何让我们的程序和浏览器输出结果一致呢?——添加headers。只需要添加一行就可以了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests

url = 'http://steamcommunity.com/app/433850/reviews/?browsefilter=toprated&snr=15_reviews'headers = {    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3'}
html = requests.get(url, headers=headers).text

第四步,the more, the better

这个时候我们发现,当我们使用浏览器时,只要滚动到页面底部,就会加载出另外10条评测。

那么如何用Python代码来实现这些额外内容的抓取呢? 本着空穴不来风的态度,我们要坚信,我们自己的电脑本地肯定不会凭空变出内容来的,那么这个下拉加载的过程中肯定发生了新的网络请求。打开Firebug的网络面板,点选保持。查看请求的情况。

很显然,这就是每次下拉加载的新内容所在的请求。我们只要继续模拟这个请求就可以了。 分析它的具体参数。

根据参数名,我们可以大概猜测出其中大部分参数的含义。 其中比较重要的几个是: offset 偏移值,固定为10,也就是每次获取新的10条。 其余几个2,是控制页数的,也就是需要翻页的话,只要把2相应地换成3 4 5…就可以了。 至于appHubSubSection、browsefilter、filterLanguage和l这几个,我是在之后的尝试中发现的其真正含义。这里暂时先不管了。

接下来通过我们刚才的发现,尝试抓取50条评测。对于参数有两种处理办法,一种是用字典作为请求参数payload,另一种是直接拼接URL,这次我们选择后者。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests
from bs4 
import BeautifulSoup

headers = {    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3'}for i in range(1, 6):
    url = 'http://steamcommunity.com/app/433850/homecontent/?userreviewsoffset=' + str(10 * (i - 1)) + '&p=' + str(i) + '&workshopitemspage=' + str(i) + '&readytouseitemspage=' + str(i) + '&mtxitemspage=' + str(i) + '&itemspage=' + str(i) + '&screenshotspage=' + str(i) + '&videospage=' + str(i) + '&artpage=' + str(i) + '&allguidepage=' + str(i) + '&webguidepage=' + str(i) + '&integratedguidepage=' + str(i) + '&discussionspage=' + str(i) + '&numperpage=10&browsefilter=toprated&browsefilter=toprated&appid=433850&appHubSubSection=10&l=schinese&filterLanguage=default&searchText=&forceanon=1'
    html = requests.get(url, headers=headers).text
    soup = BeautifulSoup(html, 'html.parser')  # 如果装了lxml,推荐把解析器改为lxml
    reviews = soup.find_all('div', {'class': 'apphub_Card'})    
    for review in reviews:
        nick = review.find('div', {'class': 'apphub_CardContentAuthorName'})
        title = review.find('div', {'class': 'title'}).text
        hour = review.find('div', {'class': 'hours'}).text.split(' ')[0]
        link = nick.find('a').attrs['href']
        comment = review.find('div', {'class': 'apphub_CardTextContent'}).text
        print(nick.text, title, hour, link, )
        print(comment.split('\n')[3].strip('\t'))

至此我们就可以随心所欲地通过控制页数来控制抓取数量了。 当然了,在我给大佬的最终实现里,是通过while True加跳出break的方法来抓取所有评测的。鉴于评测可能非常非常多,大家一般也用不到,少量抓取还是直接自己控制参数吧~

第五步,save and load

之前写代码的过程中,我们都是直接在控制台打印内容。总不能让大佬到控制台手动复制粘贴吧,还是要把结果存起来的。

我之前其实很喜欢把结果通过xlwt库存到Excel文件里,但是有些时候会出错,性能也不够好。后面发现了一种更简单直接的操作,那就是通过在txt文件中添加制表符分隔,在粘贴进excel时实现自动分列。

现在直接添加写入文件的相关代码就可以了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
file = open('steam.txt', 'w+', encoding='utf-8')
file.write() # balabala
file.close()

第六步,做一点简单的情感分析

只有数据不好玩呀。现在流行搞数据分析。我们也来玩一玩。 http://bosonnlp.com/ boson提供免费的语义接口试用。自行注册之后获取API_TOKEN。其中今天用到的情感分析接口的文档如下: http://docs.bosonnlp.com/sentiment.html

这篇文章的内容够多了…就不再赘述详情了。之后还会写文章来谈。直接给代码了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests
import json
def sen_from_text(text):
    SENTIMENT_URL = 'http://api.bosonnlp.com/sentiment/analysis'
    h = {'X-Token': 'balabala'} # your token
    data = json.dumps(text)
    resp = requests.post(SENTIMENT_URL, headers=h, data=data.encode('utf-8'))
    resp = json.loads(resp.text)    # print(resp)
    front = float(resp[0][0])    
    return front

返回结果中的数字越接近0,负面情绪越高;越接近于1,证明情绪越高。 还是测试前50条的评论。

可以发现,推荐的评论情绪偏于证明。而不推荐的评论中,虽然有少量的异常值,但是可以看到评论中存在明显的正面性语言。其他大部分数值是符合的。

最后附上此次文章的全部代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests
from bs4 import BeautifulSoup
import json
def sen_from_text(text):
    SENTIMENT_URL = 'http://api.bosonnlp.com/sentiment/analysis'
    h = {'X-Token': 'balbala'} # your token
    data = json.dumps(text)
    resp = requests.post(SENTIMENT_URL, headers=h, data=data.encode('utf-8'))
    resp = json.loads(resp.text)    # print(resp)
    front = float(resp[0][0])    
    return front

headers = {    'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3'}
file = open('steam.txt', 'w+', encoding='utf-8')
for i in range(1, 6):
    url = 'http://steamcommunity.com/app/433850/homecontent/?userreviewsoffset=' + str(10 * (i - 1)) + '&p=' + str(
        i) + '&workshopitemspage=' + str(i) + '&readytouseitemspage=' + str(i) + '&mtxitemspage=' + str(
        i) + '&itemspage=' + str(i) + '&screenshotspage=' + str(i) + '&videospage=' + str(i) + '&artpage=' + str(
        i) + '&allguidepage=' + str(i) + '&webguidepage=' + str(i) + '&integratedguidepage=' + str(
        i) + '&discussionspage=' + str(
        i) + '&numperpage=10&browsefilter=toprated&browsefilter=toprated&appid=433850&appHubSubSection=10&l=schinese&filterLanguage=default&searchText=&forceanon=1'
    html = requests.get(url, headers=headers).text
    soup = BeautifulSoup(html, 'html.parser')  # 如果装了lxml,推荐把解析器改为lxml
    reviews = soup.find_all('div', {'class': 'apphub_Card'})    
    for review in reviews:
        nick = review.find('div', {'class': 'apphub_CardContentAuthorName'})
        title = review.find('div', {'class': 'title'}).text
        hour = review.find('div', {'class': 'hours'}).text.split(' ')[0]
        link = nick.find('a').attrs['href']
        comment = review.find('div', {'class': 'apphub_CardTextContent'}).text.split('\n')[3].strip('\t')
        sen = sen_from_text(comment)        # print(nick.text, title, hour, link, )

        file.write(
            nick.text + '\t' + title + '\t' + str(sen) + '\t' + hour + '\t' + link + '\t' + comment + '\n')
file.close()

今天这篇写的十分草率。没有校稿,中间也漏掉了许多细节。第一次用Markdown排版代码也是各种问题……大家有问题的话可以在后台留言交流。

就爬虫本身我自己已知的都有很多问题,比如访问频率限制反爬,一些异常内容导致的页面解析失败,一些emoji字符导致的编码失败,等等。大部分问题我已经解决了。有关STEAM应该还会写一到两篇文章,会继续丰富内容,重构代码,解决问题的。

撒花。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 不二小段 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
5 条评论
热度
最新
大佬同求更新userreviewscursor的方法,设置循环中设置停顿时间可以吗?
大佬同求更新userreviewscursor的方法,设置循环中设置停顿时间可以吗?
回复回复点赞举报
userreviewscursor参数获取可以在评论首页html name="userreviewscursor" value="xxxxxx"获取,每拉取一次新评论需要更新该参数。steam限制了访问频率,过快会导致获取不到正确的userreviewscursor而无法爬后续评论
userreviewscursor参数获取可以在评论首页html name="userreviewscursor" value="xxxxxx"获取,每拉取一次新评论需要更新该参数。steam限制了访问频率,过快会导致获取不到正确的userreviewscursor而无法爬后续评论
22点赞举报
大佬,能不能请教一下更新这个"userreviewscursor"参数的方法啊,十分感谢
大佬,能不能请教一下更新这个"userreviewscursor"参数的方法啊,十分感谢
回复回复点赞举报
看源码呀,过去这么久了,我也不知道
看源码呀,过去这么久了,我也不知道
回复回复点赞举报
补充一下,steam下拉获取评论新增了一个 userreviewscursor 参数。按原有的url只能获取全十条参数。
补充一下,steam下拉获取评论新增了一个 userreviewscursor 参数。按原有的url只能获取全十条参数。
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
【Python爬虫】听说你又闹书荒了?豆瓣读书9.0分书籍陪你过五一
五一将至,又到了学习的季节。目前流行的各大书单主打的都是豆瓣8.0评分书籍,却很少有人来聊聊这9.0评分的书籍长什么样子。刚好最近学了学python爬虫,那就拿豆瓣读书来练练手。
弗兰克的猫
2019/05/25
5000
网络连接有问题?学会用Python下载器在eBay上抓取商品
网络连接有时候会很不稳定,导致我们在浏览网页或下载文件时遇到各种问题。有没有一种方法可以让我们在网络中断或缓慢的情况下,也能够获取我们想要的信息呢?答案是肯定的,那就是使用Python下载器。
jackcode
2024/01/25
2280
网络连接有问题?学会用Python下载器在eBay上抓取商品
Python爬虫入门教程——爬取自己的博
互联网时代里,网络爬虫是一种高效地信息采集利器,可以快速准确地获取网上的各种数据资源。本文使用Python库requests、Beautiful Soup爬取CSDN博客的相关信息,利用txt文件转存。
py3study
2020/01/20
7800
【Python爬虫实战入门】:笔趣阁小说爬取,一篇教你爬虫入门
简介:requests模块 官方文档:https://requests.readthedocs.io/projects/cn/zh-cn/latest/
爱喝兽奶的熊孩子
2024/08/06
5780
【Python爬虫实战入门】:笔趣阁小说爬取,一篇教你爬虫入门
Python爬虫学习 煎蛋网全站妹子图爬虫
通过上一篇文章的爬取过程,我们基本上理解了抓取一个网站的大致流程。因为一个网站虽然有很多页,但是大部分网站每一页的HTML标签内容都是相同的。我们只要获取到一页的内容,就可以获得所有页的内容了。那么开始之前,我们来分析一下煎蛋网妹子图页面的URL。
python学习教程
2020/06/09
1.5K0
​Python爬虫--- 1.5 爬虫实践: 获取百度贴吧内容
原文链接:https://www.fkomm.cn/article/2018/7/22/21.html
圆方圆PYTHON学院
2018/12/17
1.7K0
​Python爬虫--- 1.5 爬虫实践: 获取百度贴吧内容
数据获取:​如何写一个基础爬虫
写好一个爬虫最基本的是做好页面分析,找到链接和规律,这样在写爬虫的时候就可以有方向和目的性。接下来,我们就以爬虫最常用的豆瓣评分TOP250的内容作为爬虫的demo,以此来学习使用相关知识。
马拉松程序员
2023/09/02
3310
数据获取:​如何写一个基础爬虫
python用BeautifulSoup库简单爬虫入门+案例(爬取妹子图)
(adsbygoogle = window.adsbygoogle || []).push({});
双面人
2019/04/10
1.5K0
Python爬虫利器二之Beautif
简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据。官方解释如下:
py3study
2020/01/06
7860
Python3爬取steam优惠
妈妈再也不用担心我不知道那些游戏没有打折了,一键爬取steam优惠名单,就是写到钱的部分程序崩溃了,以至于只有游戏名
Elapse
2020/08/17
1K0
XHR请求解密:抓取动态生成数据的方法
在如今动态页面大行其道的时代,传统的静态页面爬虫已无法满足数据采集需求。尤其是在目标网站通过XHR(XMLHttpRequest)动态加载数据的情况下,如何精准解密XHR请求、捕获动态生成的数据成为关键技术难题。本文将深入剖析XHR请求解密的原理及实现方法,详细介绍5种主流方案,并以Steam游戏商店为案例,展示如何采集游戏介绍与评论数据。
jackcode
2025/03/05
1280
XHR请求解密:抓取动态生成数据的方法
用Python写一个小爬虫吧!
学习了一段时间的web前端,感觉有点看不清前进的方向,于是就写了一个小爬虫,爬了51job上前端相关的岗位,看看招聘方对技术方面的需求,再有针对性的学习。
py3study
2020/01/19
1.2K0
用Python写一个小爬虫吧!
分析新闻评论数据并进行情绪识别
爬取新闻评论数据并进行情绪识别的目的是为了从网页中抓取用户对新闻事件或话题的评价内容,并从中识别和提取用户的情绪或态度,如积极、消极、中立等。爬取新闻评论数据并进行情绪识别有以下几个优势:
jackcode
2023/07/06
4190
分析新闻评论数据并进行情绪识别
Python爬虫入门教程:豆瓣读书练手爬虫
Python现在非常火,语法简单而且功能强大,很多同学都想学Python!所以小的给各位看官们准备了高价值Python学习视频教程及相关电子版书籍,欢迎前来领取!
python学习教程
2019/07/10
7170
Python爬虫入门教程:豆瓣读书练手爬虫
python爬虫之——爬取煎蛋网图片
事先声明:本人之前并没有听说过什么煎蛋网,代码学习来自其他网站,仅供学习使用。 import requests import os import time from bs4 import BeautifulSoup # 发出请求获得HTML源码 def get_html(url): # 指定一个浏览器头 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.3
种花家的奋斗兔
2020/11/13
5210
python 爬取租房信息存储至mysql数据库
import requests from bs4 import BeautifulSoup
小末快跑
2019/07/03
1.8K0
【python爬虫 2】BeautifulSoup快速抓取网站图片
学习,最重要的是要了解它,并且使用它,正所谓,学以致用、本文,我们将来介绍,BeautifulSoup模块的使用方法,以及注意点,帮助大家快速了解和学习BeautifulSoup模块。有兴趣了解爬虫的小伙伴们,赶快学起来吧。
大家一起学编程
2022/01/25
1.4K0
【python爬虫 2】BeautifulSoup快速抓取网站图片
暑假学习爬虫の笔记
注意:该网页内容必须为:text(content-type: text/plain; charset=utf-8)
Moemu
2023/05/04
2680
用Python抓取亚马逊动态加载数据,一文读懂
亚马逊页面的动态加载主要基于现代前端技术,如AJAX、JavaScript框架(React、Vue.js)和WebSockets。这些技术使得页面内容在用户交互(如滚动、点击)或页面加载后通过异步请求从服务器动态获取并渲染。例如,商品列表、用户评论和价格信息等可能不会在页面初次加载时全部展示,而是通过JavaScript动态加载。
小白学大数据
2025/02/19
1280
Python 高级实战:基于自然语言处理的情感分析系统
在大数据和人工智能迅猛发展的今天,自然语言处理(NLP)作为人工智能的重要分支,已经深入到我们的日常生活和工作中。情感分析作为NLP中的一个重要应用,广泛应用于市场分析、舆情监控和客户反馈等领域。本文将讲述一个基于Python实现的情感分析系统,旨在帮助大家进一步提升在NLP领域的技能。
摸五休二
2024/11/20
2290
推荐阅读
相关推荐
【Python爬虫】听说你又闹书荒了?豆瓣读书9.0分书籍陪你过五一
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档