这次的案例中我们会接触到 Ajax 动态加载的网页, 可以看到, 包括下一页等很多信息块都没有链接出线, 所以就页数遍历上面就不能自己构造了 (虽然这不是重点), 这里主要的难点是 Ajax 加载我们不能直接获取到网页的元数据, 可以发现在翻页过程中网页 url 并没有发生变化, 因为此处并没有将数据保存到其他网页, 这里就涉及到上面所说的动态加载了, 这样我们就需要自己去着手分析网页内容了
image.PNG
首先我们右键检查, 切换到 network 查看网页回馈的信息, 选择此处的 XHR 还可以过滤掉不需要的数据, 勾选后面的 diasble cache 还可以禁止缓存 (网站开发中调试常用), 更多内容可以自己去了解一下如何分析网页以及 Ajax 工作原理
image.PNG
这里我们可以看到不止一项内容指向网页, 我们要如何来分析出我们所需的数据呢?
这里我们可以选择 preview, 这里通常是网页返回的一些数据, 我们就从这里着手去查看有没有网页内的数据源, 可以发现, 这里的最后一项里面慢慢点开有很多数据, 在很内层的 result 里面就有刚好和网页页面数据数目匹配的项, 仔细检查的确是很类似, 我们之后去选定这一条数据的 Headers, 去里面寻找我们需要的网页真正的 url
image.PNG
直接访问返回一些错误, 说明肯定是遗漏了什么地方, 我们再次查看 url
image.PNG
我们往下看, 发现有额外的数据项出现, 我们 url 里面出现的很多参数这里也有出现, 我们点击下一页查看参数变化, 发现除了 pn 和 first 有变化外其他都是常值, 不难猜出这是表示页数和是否为首页的参数
image.PNG
所以我们在这里可以构造一个 form_data 用于验证, 访问头中也可以定义一些头信息用于伪装身份
- headers = {
- 'Accept-Language': "zh-CN,zh;q=0.9",
- 'Host': 'www.lagou.com',
- 'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) ApplewebKit/537.36 (Khtml, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
- 'Referer': "https://www.lagou.com/jobs/list_python?city=北京&cl=false&fromSearch=true&labelWords=&suginput=",
- 'Cookie': "_ga=GA1.2.910872852.1537274650; _gid=GA1.2.551069079.1537274650; user_trace_token=20180918204408-89394348-bb40-11e8-a1fb-525400f775ce;"
- "LGUID=20180918204408-89394691-bb40-11e8-a1fb-525400f775ce; index_location_city=北京;"
- "JSESSIONID=ABAAABAAADEAAFI9B8A5B922B0F62DE98F3D76FFB498FD3; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1537274650,1537343453;"
- "LGSID=20180919155053-bbaaf688-bbe0-11e8-baf2-5254005c3644;"
- "PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=;"
- "Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1537343456; LGRID=20180919155055-bd698539-bbe0-11e8-a233-525400f775ce; TG-TRACK-CODE=search_code;"
- "SEARCH_ID=d8d49e5d780449e4adf77e35cbf240a9",
- 'Accept': "application/json, text/javascript, */*; q=0.01",
- 'X-Anit-Forge-Code': "0",
- 'X-Anit-Forge-Token': None,
- 'X-Requested-With': 'XMLHttpRequest'
- }
- for x in range(1,31):
- form_data = {
- 'first': 'false',
- 'pn': x,
- 'kd': 'python'
- }
- response = requests.post("https://www.lagou.com/jobs/positionAjax.json?city=北京&needAddtionalResult=false", headers=headers, data=form_data)
之后我们更改一下页数区间, 简单打印一下网页返回文本, 将它 JSON 化看看效果
image.PNG
仔细观察的话不难看出和之前 network 中分析出的数据很像, JSON 数据可以去到 https://www.json.cn/# 进行分析压缩展示
image.PNG
这里的话我们就已经获取到了 success 这一级的数据, 我们一级一级向下面获取, 然后将 positions 数据添加到空列表中
- json_result = response.JSON()
- page_positions = json_result['content']['positionResult']['result']
- #extend 方法可以把一个列表添加到另一个列表
- positions.extend(page_positions)
image.PNG
完整代码
- import requests
- from bs4 import BeautifulSoup
- import time
- import JSON
- def get_page():
- headers = {
- 'Accept-Language': "zh-CN,zh;q=0.9",
- 'Host': 'www.lagou.com',
- 'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
- 'Referer': "https://www.lagou.com/jobs/list_python?city=北京&cl=false&fromSearch=true&labelWords=&suginput=",
- 'Cookie': "_ga=GA1.2.910872852.1537274650; _gid=GA1.2.551069079.1537274650; user_trace_token=20180918204408-89394348-bb40-11e8-a1fb-525400f775ce;"
- "LGUID=20180918204408-89394691-bb40-11e8-a1fb-525400f775ce; index_location_city=北京;"
- "JSESSIONID=ABAAABAAADEAAFI9B8A5B922B0F62DE98F3D76FFB498FD3; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1537274650,1537343453;"
- "LGSID=20180919155053-bbaaf688-bbe0-11e8-baf2-5254005c3644;"
- "PRE_UTM=; PRE_HOST=; PRE_SITE=; PRE_LAND=https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=;"
- "Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1537343456; LGRID=20180919155055-bd698539-bbe0-11e8-a233-525400f775ce; TG-TRACK-CODE=search_code;"
- "SEARCH_ID=d8d49e5d780449e4adf77e35cbf240a9",
- 'Accept': "application/json, text/javascript, */*; q=0.01",
- 'X-Anit-Forge-Code': "0",
- 'X-Anit-Forge-Token': None,
- 'X-Requested-With': 'XMLHttpRequest'
- }
- positions = []
- for x in range(1,31):
- form_data = {
- 'first': 'false',
- 'pn': x,
- 'kd': 'python'
- }
- response = requests.post("https://www.lagou.com/jobs/positionAjax.json?city=北京&needAddtionalResult=false", headers=headers, data=form_data)
- json_result = response.JSON()
- page_positions = json_result['content']['positionResult']['result']
- #extend 方法可以把一个列表添加到另一个列表
- positions.extend(page_positions)
- time.sleep(3)
- print("*************************")
- print(page_positions)
- def main():
- get_page()
- if __name__ == '__main__':
- main()
大家可以着手去尝试一下, 中间有些问题我就直接略过了, 比如拉勾网的处理机制, 给你一套假数据什么的 (有够坑), 所以大家一定要注意请求方法 (get,post), 请求表单的提交等, 还有对 JSON 数据的过滤等等
更多代码详情参考我的 GitHub https://github.com/MAYA-MUYI/spider
来源: http://www.jianshu.com/p/f01a052f5608