【scrapy爬虫】爬取华为应用市场中所有应用的评论数据
前言
项目需要爬取评论数据,在此做一个记录,这里爬取的是web端的数据,以后可能会考虑爬取android app中的数据。
一、安装并创建Scrapy项目
Scrapy官方文档:https://docs.scrapy.org/en/latest/intro/install.html
Scrapy是一个比较好用的python爬虫框架,官方文档写得也比较详细。可以直接运行以下命令安装:
pip install Scrapy
安装完毕后,需要创建Scrapy项目,相当于是一个爬虫项目框架,在想要放置项目的地方打开命令行并输入以下命令会自动创建一个名为[project_name]
的文件夹,比如我这里的[project_name]
是appstore
,文件夹中会自动生成的一些文件。
scrapy startproject appstore
appstore/scrapy.cfg
中包含了用于启动爬虫的一些基础配置,一般不用管它。appstore/appstore/items.py
:定义了爬取到的数据格式类,在这里面创建类来存放爬取到的数据的item格式。appstore/appstore/middlewares.py
:定义了爬虫中间键的一些行为,我一般也不会去动它。appstore/appstore/pipelines.py
:定义了爬取到item后对其进行的处理。appstore/appstore/settings.py
:是爬虫配置文件。appstore/appstore/spiders/
:这个目录下存放的是爬虫,也就是向网页发送请求并受到应答然后进行数据处理的过程。
二、爬取应用市场评论过程
爬取网页信息有两个常用的方法:
- 直接通过xpath解析html文件
- 依据特定格式构造请求获取json数据进行解析
显然前者更简单方便一些,但是现在许多网页都是动态的,所以后者泛用性更强一些,这里我爬取华为应用市场上所有应用的评论信息主要使用的是后面一种方法。
1. Scrapy爬虫运行流程
首先需要大致了解Scrapy的爬虫是如何运作的,分为以下几个步骤:
- Step1: 在项目的spiders文件夹中新建一个.py文件,比如huawei.py,一般来说每一个文件代表一个爬虫,也就是对某一个网页的爬取策略。
- Step2: 创建一个类继承自
scrapy.Spider
,类中至少需要有name
、allowed_domain
、start_urls
变量以及一个函数parse(self)
。其中name
是此爬虫的唯一标识,之后启动时通过指定name
来判断启动哪个爬虫(因为spiders文件夹中可能包含多个爬虫文件);allowed_domain
用来指定当前爬虫可以访问的主域名;start_urls
用来指定首先获取的页面,而此获取结果将会交由parse
函数进行处理。每个爬虫中的处理函数可能有很多个,命名格式一般是parse_xxx
之类的,用来处理多级页面,比如parse
处理完主页面之后构造新的请求获取二级页面信息并通过parse_second
进行处理,但不管怎么样都会包含一个parse
函数。
import scrapy
class HuaWei(scrapy.Spider):name = "huawei"allowed_domains = ['appstore.huawei.com', 'web-drcn.hispace.dbankcloud.cn']start_urls = ['https://web-drcn.hispace.dbankcloud.cn/uowap/index?method=internal.getTemplate&serviceType=20&zone=&locale=zh']def parse(self, response):pass
- step3: 爬虫编写好之后,在项目根目录(也就是scrapy.cfg文件的同级目录)打开命令行,并输入以下命令启动爬虫:
scrapy crawl huawei
2. 页面分析
首先,通过浏览器访问应用市场,分析一下想要爬取网页的基本信息,这里我想要爬取应用市场中所有应用的评论,所以首先需要进入到所有应用的详细界面,然后在详细界面中展开评论进行爬取,基本的思路是:对每一个分类–>对每一个子分类–>展开每一个应用–>获取应用全部评论。
爬取的初始页面是https://appgallery.huawei.com/#/Apps
,浏览器中使用F12启动开发者模式,调试网页前端代码,我们希望的是能够找到页面排版的某些规律。
页面分析过程一
我们发现不管在应用分类的选项卡中选择哪一个分类或是子分类,url都不会变。也就是说,选择分类后显示对应的应用列表这一功能是动态实现的,我们没办法通过抓取html中的信息来获取不同分类的应用列表,那么我们只能通过自己构造请求获取json数据的方式爬取信息。
首先,打开调试窗口中的Network选项卡来分析获取不同分类应用列表时的网络数据包:
除了第一个数据包以外,后面的都是获取应用图标数据,也就是说第一个数据包里面就包含了应用的其他数据,查看此数据包中的request_url为:
https://web-drcn.hispace.dbankcloud.cn/uowap/index
?method=internal.getTabDetail
&serviceType=20
&reqPageNum=1
&uri=8e62cf6d238c4abdb892b400ff072f43
&maxResults=25
&zone=
&locale=zh
我们直接在浏览器中访问此url,可以得到一个json文件,分析后发现此json文件中包含了列表中应用的信息。点击不同的分类、子分类,获取不同的request_url,我们发现,每一个子分类的request_url都只有uri字段不一样,且默认情况都只显示第1页的25个应用。也就是说我们以此request_url为模板,修改uri字段实现获取不同类别应用列表,修改reqPageNum字段获取列表中的多页应用。
页面分析过程二
手动点进每一个应用的详细界面时,我们发现,不同应用的详细界面的url只有最后的定位有不同,比如腾讯视频与优酷视频这两个应用详细界面的url分别是:
多观察几个应用就会发现最后的那一串代码应该是类似于应用唯一标识符一样的东西。而在上一步中,我们可以发现在获取的每个应用信息中包含能够找到这些标识符(‘appid’键的值),于是我在这里尝试直接以这种格式构造url请求获取页面,但是失败了,猜测可能是页面重定向的问题,没办法,只能按部就班地通过其它方式继续分析。
通过F12查看页面排版,每一个app卡片中虽然有app名称以及一些其他信息,但是找不到app详细页面的链接,因为获取应用详细信息功能被写成了使用js动态获取的,因此我们没办法直接从html界面中获取,所以依旧采用构造request_url的方法获取json数据。
与分析过程一类似,我们可以获取以下的request_url:
https://web-drcn.hispace.dbankcloud.cn/uowap/index
?method=internal.getTabDetail
&serviceType=20
&reqPageNum=1
&maxResults=25
&uri=app%7CC174391
&shareTo=
¤tUrl=https%253A%252F%252Fappgallery.huawei.com%252F%2523%252Fapp%252FC174391
&accessId=
&appid=C174391
&zone=
&locale=zh
通过此request_url获取的json中包含了应用的详细信息,实际上通过测试,其中的reqPageNum、maxResults、shareTo、currentUrl、accessId、appid、zone、locale字段都是不需要的,而又发现uri字段中后面的“C174391”是当前应用的appid,也就是说我们只需要修改uri字段的“app%7C”后面的字符串为不同应用的appid(可以在分析过程一中的json文件里获取),就可以获取不同应用的详细信息。
页面分析过程三
有了上面两次分析的经验,我们继续来爬取每个应用的评论数据,发现这些数据也是通过js动态获取的,于是继续分析request_url,格式如下:
https://web-drcn.hispace.dbankcloud.cn/uowap/index
?method=internal.user.commenList3
&serviceType=20
&reqPageNum=1
&maxResults=25
&appid=C2002
&version=10.0.0
&zone=
&locale=zh
与之前类似,我们可以通过修改appid字段爬取不同应用的评论,通过修改reqPageNum字段爬取多页评论。
3. 爬虫实现
整个爬取过程就是:构造request_url请求获取json数据–>解析json数据–>构造新的request_url获取json数据–>…
下面是爬虫中的一个处理函数,功能是处理每一个应用的详细信息并构造获取评论的request_url发送新的请求,接下来依次说明其中的关键部分。
def app_parse(self, response):"""解析应用,获取应用名称、描述、资费、版本、开发者,然后转至appcomment_parse进行处理:param resonse::return:"""appid = response.meta['appid']app_json = json.loads(response.text)Name = app_json.get('layoutData')[0].get('dataList')[0].get('name')Star = app_json.get('layoutData')[0].get('dataList')[0].get('intro')Downloads = app_json.get('layoutData')[0].get('dataList')[0].get('stars')Price = app_json.get('layoutData')[3].get('dataList')[0].get('tariffDesc')Version = app_json.get('layoutData')[3].get('dataList')[0].get('version')Developer = app_json.get('layoutData')[3].get('dataList')[0].get('developer')Description = app_json.get('layoutData')[7].get('dataList')[0].get('appIntro').replace('\n', '')AppData = AppItem(AppId=appid,AppName=Name,AppDesc=Description,AppPrice=Price,AppVersion=Version,AppDeveloper=Developer,AppStar=Star,AppDownloads=Downloads)yield AppDatafor pagenum in range(1, 20):request_url = "https://web-drcn.hispace.dbankcloud.cn/uowap/index?method=internal.user.commenList3&serviceType=20&reqPageNum={}&maxResults=25&appid={}&version=10.0.0&zone=&locale=zh".format(pagenum, appid)yield scrapy.Request(url=request_url, callback=self.appcomment_parse, meta={'appid': appid})
解析json并构造请求
第8行中通过json.loads
将响应解析为json格式,并在后续使用键值与index访问里面的信息。
将数据保存在items中
在items.py文件中定义好Item类之后,可以在此新建一个Item对象,并在填入相应的值,将此item返回交由pipeline.py进行处理。
# items.py
class AppItem(scrapy.Item):AppId = scrapy.Field()AppName = scrapy.Field()AppDesc = scrapy.Field()AppPrice = scrapy.Field()AppVersion = scrapy.Field()AppDeveloper = scrapy.Field()AppStar = scrapy.Field()AppDownloads = scrapy.Field()
yield是python中的一个关键词,与return类似,会让函数返回此关键词修饰的表达式值,与return不同的是,yield在返回一个值后会继续执行后面的代码,而return不会。
构造新的请求
在最后一行中针对所有评论列表构造新的request_url以获取评论信息,并通过scrapy.Request
发送请求,其中callback
指定用于处理此请求响应的处理函数,而meta
中包含了想要传递给callback函数的信息。
item数据的处理
在爬取数据的过程中,处理函数会实时将不同的item返回并交由pipeline进行处理,此时需要在pipeline.py中指定如何处理这些item,比如在此我把数据全都记录入csv表格中。pipeline类中必须定义process_item
函数来处理每一个item,而__init__
与close_spider
都是可选的。
class AppStorePipeline:def __init__(self):self.app_list = []self.comment_list = []def process_item(self, item, spider): # 接收到item时调用的函数if isinstance(item, AppItem):self.app_list.append(dict(item))elif isinstance(item, CommentItem):self.comment_list.append(dict(item))return itemdef close_spider(self, spider): # 当爬虫关闭时调用的函数df_app = pd.DataFrame(self.app_list)df_comment = pd.DataFrame(self.comment_list)df_app.to_csv('app_info.csv')df_comment.to_csv('comment_info.csv')
代码分享
整个项目我放在了github上,在python3.7下可以正常使用,如果有什么问题欢迎大家指正。
github项目地址:https://github.com/LSY-C/scrapy_hauweiappstore_comment
分别爬取的一些应用信息以及应用的评论信息,数据结构如下:
【scrapy爬虫】爬取华为应用市场中所有应用的评论数据相关推荐
- python3 爬虫 爬取华为应用市场 APP应用评论(一)爬取全部评论——学霸君
python3 爬虫 爬取华为应用市场 APP应用评论(一)爬取全部评论--学霸君 import requests import re import requests from bs4 import ...
- python3 爬虫 爬取华为应用市场 APP应用评论(一)爬取全部评论——作业帮
python3 爬虫 爬取华为应用市场 APP应用评论(一)爬取全部评论--作业帮 import requests import re import requests from bs4 import ...
- python3 爬虫 爬取华为应用市场 APP应用评论(一)爬取全部评论——小猿搜题
python3 爬虫 爬取华为应用市场 APP应用评论(一)爬取全部评论--小猿搜题 import requests import re import requests from bs4 import ...
- Python爬虫-爬取手机应用市场中APP下载量
一.首先是爬取360手机助手应用市场信息,用来爬取360应用市场,App软件信息,现阶段代码只能爬取下载量,如需爬取别的信息,请自行添加代码. 使用方法: 1.在D盘根目录新建.tet文件,命名为Ap ...
- Python爬虫:爬取华为应用市场app数据
爬取华为应用商店的所有APP名称和介绍,因为页面数据是ajax异步加载的,所以要找到对应的接口去解析数据. 爬取华为应用市场app数据 一.分析网页 1. 分析主页 2. 分析appid 3. 分析u ...
- python3 爬虫数据处理 爬取华为应用市场 APP应用评论(二)根据评论生成词云——小猿搜题
python3 爬虫&数据处理 爬取华为应用市场 APP应用评论(二)根据评论生成词云--小猿搜题 # 导入扩展库 import re # 正则表达式库 import collections ...
- python3 爬虫数据处理 爬取华为应用市场 APP应用评论(二)根据评论生成词云——学霸君
python3 爬虫&数据处理 爬取华为应用市场 APP应用评论(二)根据评论生成词云--学霸君 # 导入扩展库 import re # 正则表达式库 import collections # ...
- python3 爬虫数据处理 爬取华为应用市场 APP应用评论(二)根据评论生成词云——作业帮
python3 爬虫&数据处理 爬取华为应用市场 APP应用评论(二)根据评论生成词云--作业帮 # 导入扩展库 import re # 正则表达式库 import collections # ...
- Python Scrapy 爬虫 - 爬取多级别的页面
Python Scrapy 爬虫 - 爬取多级别的页面 互联网中众多的 scrapy 教程模板,都是爬取 下一页 → \rightarrow →下一页形式的,很少有 父级 → \rightarrow ...
- python3爬取华为应用市场APP安装包实战
** python3爬取华为应用市场APP安装包实战 ** 一.用浏览器访问华为应用市场,搜索APP并观察URL规律 比如我们要下载微信,那么在搜索框输入微信并回车,会发现url变成http://ap ...
最新文章
- linux每天进步一点点-7月4.5.6日
- linux中执行jmx脚本,在linux服务器下JMeter如何执行jmx性能脚本
- maven的pom.xml中profiles的作用
- pytorch教程龙曲良21-25
- 浅谈OCR之Tesseract
- [渝粤教育] 中国地质大学 事故应急救援 复习题
- 【ZOJ - 3212 】K-Nice (构造)
- MSYS2 + MinGW-w64 + Git + gVim 环境配置
- 写一段代码提高内存占用_记录一次生产环境中Redis内存增长异常排查全流程!...
- 用SQL产生连续的自然数
- Linux修改文件时候出现崩溃,产生了一个.swap交换文件,如何修复?
- 回溯法2——和尚挑水
- oracle服务器端怎么打开监听_Oracle11g监听器(Listener)的一些基础知识
- Java对List集合排序
- Shapley Explanation Networks
- 互联网寒冬中的跳槽指南
- java网络编程--UDP程序设计
- 华为机试真题 Python 实现【最短木板长度】【100%通过率】【2022.11 Q4 新题】
- 字符编码和字符集基础知识
- 汽车电子功能安全标准ISO26262解析(五)——FTA
热门文章
- 贾扬清谈云原生 - 让数据湖加速迈入3.0时代
- Python之ascii转中文
- 解决:vue组件顶部留有空白问题
- 微软2016校园招聘4月在线笔试2-403 Forbidden
- 多元微积分_旋度2.旋度公式推导
- 万物互联时代,谷歌、亚马逊Alexa、homekit该如何选择?
- 【Ubuntu16.04】搭建Hyperledger Fabric环境
- 概率论05 - 随机变量及其分布函数
- 苹果cms模板_苹果CMS提示“模板文件不存在”怎么办?
- LVGL笔记11--lv_btn按钮