动用浏览器内核(PhantomJS、Selenium等)的方案
优采云 发布时间: 2021-06-23 00:13动用浏览器内核(PhantomJS、Selenium等)的方案
那些使用浏览器内核的程序(PhantomJS、Selenium等)太重了,
上面链接中的博客解释了如何通过抓取 Ajax请求采样的数据来抓取前端渲染的网页,这是“网页内容由JavaScript生成”的主题。摘录如下:
链接:http://xlzd.me/2015/12/19/python-crawler-04
来源:xlzd 杂谈
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在抓取网页时,有时会发现HTML中没有我们需要的数据。这个时候我该怎么办?
我们的目的是抓取拉勾Python类下目前全国显示的所有招聘信息。首先,在浏览器中点击查看。如果你够细心或者网速比较慢,那么你会发现在点击Python分类后跳转到的新页面上,招聘信息的出现时间晚于页框的出现时间。至此,我们几乎可以确定招聘信息不在页面的 HTML 源代码中。我们可以通过command+option+u(windows和linux的快捷键是ctrl+u)来查看网页的源码,在源码中。页面上没有显示招聘信息。
此时,我看到的大部分教程都会教使用什么库,如何模拟浏览器环境,如何完成网页的渲染,然后获取里面的信息……永远记住对于爬虫程序,模拟浏览器通常是最糟糕的事情。只有在没有其他办法的情况下才考虑模拟浏览器环境,因为那种内存开销真的很大,效率很低。
那我们怎么处理呢?经验是,在这种情况下,大多数情况是浏览器在请求解析完HTML后,会根据js的“指令”再发送一次请求,得到页面显示的内容,然后显示给浏览器通过js渲染后的界面。好消息是,此类请求的内容往往是json格式,这样既不加重爬虫任务,又可以省去解析HTML的工作量。
好吧,继续打开 Chrome 的开发者工具。我们点击“下一步”后,浏览器发送了如下请求:
注意 positionAjax.json 请求。它的Type是xhr,它的全名是XMLHttpRequest。 XMLHttpRequest 对象可以部分更新网页,而无需将整个页面提交给服务器。所以,现在的可能性最大,我们点开后仔细观察一下:
点击后,我们在右下角找到了上面的详细信息,几个选项卡的内容表明:
通过内容观察,返回的确实是一个json字符串,里面收录了这个页面的每一条招聘信息。至少我们这里已经说清楚了,不用解析HTML就可以获取招聘信息。那么,应该如何模拟请求呢?我们切换到Headers列,注意三个地方:
上图显示了本次请求的请求方式、请求地址等信息。
上面的截图显示了这个请求的请求头。一般来说,我们需要注意Cookie/Host/Origin/Referer/User-Agent/X-Requested-With等参数。
上面的屏幕截图显示了为此请求提交的数据。根据观察,kd代表我们查询的关键字,pn代表当前页码。
那么,我们的爬虫需要做的就是根据页码不断向这个接口发送请求,解析其中的json内容,并存储我们需要的值。这里有两个问题:什么时候结束,如何获取json中有价值的内容。
我们回去重*敏*感*词*返回的json,格式化后的层次关系如下:
很容易发现content下的hasNextPage是是否有下一页,content下的结果是一个list,每一个都是一个job信息。在 Python 中,json 字符串到对象的映射可以通过 json 库来完成:
import json
json_obj = json.loads("{'key': 'value'}") # 字符串到对象
json_str = json.dumps(json_obj) # 对象到字符串
映射到Python的json字符串的“[]”类型是list,映射到Python的“{}”类型是dict。至此,分析过程完全结束,可以愉快的写代码了。具体代码这里不再给出。我希望你能自己完成。如果在写作过程中遇到问题,可以联系我寻求帮助。
总结
本篇博客介绍了在HTML源码中没有的情况下爬取一些数据的方法,适用于某些情况。