集搜客网页抓取软件(1.网页信息有两个常用的方法:1.Scrapy运行流程 )
优采云 发布时间: 2022-01-15 12:17集搜客网页抓取软件(1.网页信息有两个常用的方法:1.Scrapy运行流程
)
爬取网页信息的常用方法有两种:
显然前者更简单更方便,但现在很多网页都是动态的,所以后者更通用。这里我主要使用后一种方式来抓取华为应用市场上所有应用的评论信息。
1. Scrapy爬虫运行过程
首先,你需要对Scrapy的爬虫工作原理有一个大致的了解,分为以下几个步骤:
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
scrapy crawl huawei
2. 页面分析
首先,通过浏览器访问应用市场,分析你要爬取的网页的基本信息。这里我要爬取应用市场中所有应用的评论,所以首先需要进入所有应用的详细界面,然后在详细界面中展开评论进行爬取,基本思路是:针对每个类别->为每个子类别 -> 展开每个应用程序 -> 获取应用程序的所有评论。
抓取的初始页面是#/Apps。在浏览器中使用F12启动开发者模式,调试网页前端代码。我们希望找到一些页面布局的规则。
页面分析过程
我们发现无论在app category tab中选择哪个category或者subcategory,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_urls。我们发现每个子类的request_urls只有uri字段不同,默认只显示第1页的25个应用。也就是说,我们以request_url为模板,修改uri字段获取不同类别的应用列表,修改reqPageNum字段获取列表中的多页应用。
页面分析流程2
在手动点击各个应用的详细界面时,我们发现不同应用的详细界面的url仅在最终定位上有所不同。例如腾讯视频、优酷视频的详细界面的url为:
多观察几个应用,你会发现最后一串代码应该和应用唯一标识差不多。在上一步中,我们可以发现这些标识符('appid'键的值)可以在每个获取到的应用信息中找到,所以这里我尝试构造url请求直接获取这种格式的页面,但是它失败现在,我猜这可能是页面重定向的问题。没有办法,只能通过其他方法一步一步地继续分析。
通过 F12 查看页面布局。虽然每个应用卡片都有应用名称和一些其他信息,但是找不到应用详情页面的链接,因为获取应用详情的功能写成使用js动态获取,所以我们不能直接从html接口,所以还是用构造request_url的方法来获取json数据。
与分析过程1类似,我们可以得到如下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(可以在分析过程1中的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 AppData
for 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将response解析成json格式,后面通过key-value和index访问里面的信息。
将数据保存在项目中
在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指定用于处理该请求响应的handler函数,meta收录你的想传递给回调函数的信息。
项目数据的处理
在爬取数据的过程中,处理函数会实时返回不同的item,交给pipeline处理。这时候就需要在pipeline.py中指定如何处理这些项。例如,这里我将所有数据记录在 csv 表中。必须在管道类中定义 process_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 item
def 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')