废话少说
很庆幸暑假入了python的坑,也很庆幸选择学习爬虫,因为用python真的可以用很少的代码完成很多有趣的事情,爬虫便是其中之一。断断续续学爬虫有几个月了,现在我早已不满足于最开始单进程,单IP,爬豆瓣,糗事百科这种纯静态请求的页面,爬取这种动态请求数据的其实更有意思。因为我自己感觉做爬虫有俩个地方很爽,一个就是成功分析出了目标网站请求数据的策略,另一个地方就是成功爬到数据的时候,看着数据一条条刷刷刷的保存到本地的时候是真的爽。
学习爬虫,一定要尝试爬一爬电商平台的数据,一定要尝试逐步提高自己的爬取数据量,要不你还以为所有的网站那么容易爬呢!今天,我就来爬一爬速卖通(阿里的跨境电商平台)的用户评论。
正文
环境准备
python 环境
request库 用于发送http/https请求,接收响应
BeautifulSoup库 用于解析网页
上述环境只是因为博主习惯了而已,不是爬虫最核心的东西,搞清楚数据是怎么请求的,可以选用不同的语言和库去实现。
分析评论数据请求策略
分析请求就是看看我们目标数据是从哪个http请求请求过来的。在速卖通我们随便打开一个产品页,如下图
feedback肯定就是评论的意思,我们点击评论,并右键进入开发者工具
image.png
从谷歌开发者工具Elements选项我们可以看出评论在类.buyer-feedback这个dt元素里。
尝试1:我们从浏览器复制链接,然后用requests向该链接发出get请求
image.png
咦,评论明明在这个页面,为什么请求成功却取不到这些评论数据。
这就是动态请求数据与静态请求的区别,静态请求数据一般都是服务器端渲染好的了,你请求到的时候已经填充了数据,而动态请求是,客户端通过发送ajax请求,将数据请求到前端,然后由前端来渲染的,即用js把数据插入html页面中的,所以真正的数据是通过另一个请求得到的,所以现在的问题就是要找到这个请求评论数据的地址。
重新刷新页面,右键开发者工具 进入network选项,如下图
image.png
可以发现,现在已经有了160多个请求,所以在点击feedback之前一定要先clear掉现在所有的请求,否则你一点feedback,会出现更多请求,就不好判断是哪个请求请求得到了评论数据
clear掉之后,点击feedback,会看到你在点了feedback之后出现的请求,所以评论数据的请求地址一定在这些请求当中
这时候你基本有俩个选择,如果请求数不多的话,点击每一个请求,看看是不是;如果请求还是比较多,你可以利用谷歌开发者工具上边的请求过滤器,默认是显示全部类型的请求,因为你要找的是评论数据,那么肯定不是图片,css,media,Font等类型,最有可能的是XHR,JS,Doc
XHR即通过ajax异步请求的数据,JS即js文件,这个也是有可能的,Doc即html文档
image.png
然后我们分别点击XHR,JS,Doc,一个个试(这个没好办法,只能一个个试,但是你经验越丰富,你试出来的时间越短,比如你从请求链接里的某个英文单词,就大概可以猜出)最终在XHR,JS里都没有发现,那么按照排除法,只能在DOC里边的请求了,doc下只有俩个请求,其中一个请求中还有productEvaluation等字眼,直接告诉我,没问题,就是它了。
image.png
选择preview或者response,往下拉一拉,很快就发现了评论数据,果然不出我所料,正常人在这个时候是有点爽的。
然后,我们来看看请求信息,选择Headers
image.png
然后,我们模仿该请求来进行第二次尝试
尝试2:我们直接从浏览器复制请求头,连cookie一起复制
image.png
requests.get(url,headers=headers) 带header请求发送get请求
可以发现,我们已经正确取到了评论数据,正常人这个时候应该感觉更爽才对。
既然评论的请求地址搞清楚了,那么接下来考虑的是增大数据量爬取,看看会不会遇到什么问题,因为评论有很多页,所以我们很自然的想到可以考虑按页数爬取全部的数据,但是就在我打算写代码的时候,我才突然发现我不知道怎么写!为什么,因为我突然发现刚才这个请求里没有任何有关页数的信息!
不过,没关系,这个办法很好解决,因为页面上是有分页按钮的,所以我们点击第二页,看看第二页数据是怎么请求来的
还是按照之前的办法,先clear掉之前的请求,然后点击第二页,观察有哪些新的请求出现,这个过程和之前类似,我们很快就找到这个第二页数据的请求地址
这个请求是POST请求,然后我分析提交的数据,发现里边有一个key是page,值是2,那么这个page肯定是用来控制分页,所以其实这个接口才是真正的数据请求接口,可以根据不同的产品ID,卖家ID,页数等信息获取评论数据。到底是不是,我们继续测试,同样复制请求头,和请求数据,cookie也要正确复制,否则得不到数据
尝试3 image.png
requests.post(url,headers=headers,data=data) 可以带请求头和数据发出请求
可以发现,成功获取到了数据,至此,我找到了数据请求地址,但是接下来还有一个最复杂的问题。
我随便换一个产品ID,甚至让它为空,会发现请求到的数据还是原来的数据,如下图
image.png
我们继续观察post的数据
image.png
会注意到有一个_csrf_token:xz4r263hT4WbCYfPCtSbq3 这个值,我猜肯定这个值是根据产品ID等信息变化的,也就是只有这个token对了,才可以拿到数据。(别问我为什么可以猜到,直觉)
我们改一下这个token值
数据立刻就请求不到了!!!
搞了这么多,如果不能正确获取token,前边的分析都意义不大,总不能每次换一个产品,就手动去浏览器里手动复制token吧。
那么这个token是怎么来的呢?
经过我一天的摸索(这个我真心没什么技巧,有的是服务器端生成的,有的是通过js执行脚本生成的),我终于发现了端倪。
还记不记得我们第一次尝试,即第一页的评论是通过GET请求得到的,其实那个页面除了请求第一页评论外,还拿到了这个token值,如图
image.png
md,藏的可真深呐!!!
结论
所以最终请求策略就是
先根据productid,ownerMemberid,companyId构造一个url,如下
url1=https://feedback.aliexpress.com/display/productEvaluation.htm?productId=32466567934&ownerMemberId=223275770&companyId=232994171&memberType=seller&startValidDate=&i18n=true
向这个url发送get请求,取到token值,同时保存cookie
然后带着这个cookie,以及token和其它数据向
url2=https://feedback.aliexpress.com/display/productEvaluation.htm
post数据,就ok了
基于python requests库的 伪代码
session=requests.Session() #用session是为了保存cookie
res=session.get(url1,header=header)
# 获取token
token=get_token(res)
data={
...
'_csrf_token':token
}
comment=session.post(url2,headers=headers,data=data)
# 解析评论数据
data_list=parseComment(comment)
# 保存评论数据
store_data(data_list)
最后
到此,我们基本已经搞清楚了速卖通评论的请求策略,在下一篇文章中,我们开始采用代理IP以及多线程来编写最终代码。
网友评论