Table of Contents
问题描述
在爬取数据详情页面时候,需要将评论数(评论条数)爬取到,但是评论数和详情页面的数据不是同步请求的,在后于详情页面载入数据,如果使用urllib.request.openurl直接抓取页面,得到的结果就是在抓取的页面时,评论数还没有填充到页面上,导致无法获取评论数据。
解决思路
方案一
既然是评论数在后于详情页面上的数据加载到页面,那么可以等待一定的时间,等到评论数据也被加载并填充到页面后在去抓取页面,那不就在页面上能获取到评论数据了吗?
使用selenium:selenium-python中文文档
- selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器
但是在我的需求中,这样虽然能解决问题,但是太浪费时间,程序性能肯能会被影响。 我只需要请求一个数据字段,如果请求等待的时间太短,可能还请求不到数据就被断开,如果设置请求的时间太长,或严重拖慢程序的速度。所以在看了一些基本介绍和别人的操作后,也尝试在自己程序上使用,但是需要配置的东西太多,就果断放弃。
方案二
单独加载评论数的链接,获取评论数,这也是我解决自己问题的方法。有时候,这样的数据请求链接可以请求到数据,但是我这里不行,因为在我请求的链接中和前一步有很大的联系,如果不是在详情页面上加载数据,那么是请求不到数据的,而是被直接拦截到了登录页面,这里就需要将自己的请求的详情页面的链接封装到请求评论数的header上,伪装为正常的数据请求。
当然,知道这样做是进过自己尝试了很多方法后,向被人请教后得知的。同事是使用采集平台上的可视化化界面采集数据的,但是我们是被要求使用代码去采集数据,进过询问后得知,需要在请求的header上加上请求的前异步的链接。
开始,我使用的时这样的:
import urllib.request
def getcommentcount(preurl,suburl):
headers = {"User-Agent",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"}
prevheaders = {"Referer",preurl}
opener = urllib.request.build_opener()
opener.addheaders = [headers]
opener.addheaders = [prevheaders]
urllib.request.install_opener(opener)
file = urllib.request.urlopen(suburl)
data = file.read()
但是程序很不稳地,一直报错
Python ValueError: Invalid header name b'Https://I.Learn.Hello.Com/Detail.Htm?CourseId=117292'
传入的preurl实际上是这样的:
https://i.learn.hello.com/detail.htm?courseId=117292
将问题贴到浏览器上,看到别人是这样说的Python ValueError: Invalid header name b':authority
我也在自己程序中尝试上面的解决方案,但是并没有解决问题,我开始怀疑自己设置header的方式是错的,因为在网上别人都只是使用上面的方式设置一个参数,而我设置了两个,于是我有查找了另外一种设置header的方式。
def getcommentcount(url,suburl):
req = urllib.request.Request(suburl)
req.add_header("User-Agent","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36")
req.add_header("Referer",url)
file = urllib.request.urlopen(req)
data = file.read()
这样设置后,问题解决,没有在报错。至于什么原因,后面自己对爬虫熟悉后在慢慢摸索一下。