1、明确分析目标
爬取网站的数据之前我们一定要明确爬取的网站是哪个,哪些页面,页面哪一部分的数据。
1.1 获取拉勾网的地址
介于部分网站在访问的时候,会强制让用户进入登录和注册界面而不是主页。小编在这提醒一下小伙伴们啦!拉勾网的网址和主页图将在下面贴出,快看看你们的是不是和小编一样叭。
拉勾网网址:https://www.lagou.com/
拉勾网主页图展示如下。
如上图所示,我们观察一圈发现没有具体的招聘信息,所以这一页不是我们需要爬取的,而是需要访问的页面。我们需要爬取的是有着具体职位的页面,如下图所示(小编在主页点击了java后展示了这个页面)。
2、编写代码
爬取数据代码编写的实现,有四个最基本的步骤,具体如下所示。
1、发送请求。对于刚刚分析得到的url地址发送和get请求(并且模拟浏览器发送请求)。
2、获取数据。获取服务器返回response响应数据。
3、解析数据。提取最终想要的数据内容。此处即为招聘信息基本数据。
4、保存数据。把爬取到的数据保存至本地。(可以是表格,和csv文件或者txt文件或者一串json格式的字符串)。
2.1 发送请求
为了保证我们发送的请求,即url路径,可以拿到我们想要爬取的数据,我们需要通过浏览器自带的检查工具来查看一下。并查看一下我们需要爬取的数据存放在了页面的哪个地方。
2.1.1 输入关键字
此处以python为例,在主页输入框输入关键字:python,然后点击搜索,我们会得到如下图所示的结果。
2.1.2 打开页面检查工具
1、在页面任意除右键,选择菜单中的检查。具体操作如下图所示。
2、点击检查后,打开浏览器检查工具,如下图所示。
3、在菜单栏选择网络,如下图所示。
如上图所示我们可以看到,记录网络活动这一块为空,这里大家先别慌,我们使用快捷键Ctrl+R就会刷新网络活动记录啦。
4、使用快捷键Ctrl+R,具体效果如下图所示。
如上图,刷新后一系列的网络活动记录就显示出来了。那么我们下一步就是使用检查工具中的搜索功能对页面的内容某些进行搜索,来查看这些内容被藏在了这些网络活动记录中的哪一条里面。
2.1.3 找寻爬取数据的存放位置
拿下图中安势信息进行举例,我们通过使用检查工具中的搜索功能对安势信息进行搜索,查看安势信息被藏在了这些网络活动记录中的哪一条里面。
1、打开搜索器。点击搜索图标即可开启。
2、输入关键字:安势信息
3、如上图所示,输入关键字:安势信息,点击刷新按钮后,下方出现了搜索结果,那么它是怎么样的呢?单击进行查看,如下图所示。
观察上图我们可以发现,最后的数据变成了一行。至于我们刚刚搜索的,这一行数据太长了,太难翻了,如果有可以检索的工具就好了。
4、点击右下角显示数据的地方,快捷键Ctrl+F,继续输入关键字:安势信息,回车,如下图所示。
通过上图,最终我们发现我们需要爬取的数据就在这一条中,并且也在这个url中,即我们需要爬取的url就是地址栏中的路径,接下来我们需要去将这一条网络记录标头中的部分信息去提取出来。
2.1.4 页面具体配置信息
通过2.1.3我们可以得出爬取数据的url为:https://www.lagou.com/wn/jobs?labelWords=&fromSearch=true&suginput=&kd=python
此外我们还需要去拿4个参数:Cookie、Host、Referer、User-Agent。以下操作基于2.1.4的第4步。
1、Cookie
如上图所示,直接将Cookie中的数据全篇复制即可。
2、Host
如上图所示,Host为:www.lagou.com
3、Referer
如上图所示,Referer为:https://www.lagou.com/
4、User-Agent
如上图所示,直接将User-Agent中的数据全篇复制即可。
最后我们将1,2,3,4即Cookie、Host、Referer、User-Agent四个参数的值组合起来变为一个Headers,Headers也就是请求头,具体代码展示如下。
headers= { 'Cookie': '__lg_stoken__=74667837daa94dc4815a15e5abcc6d9d6bf9378cf0f87cf07f1cddc90c731b5dbffd39e14b57d61f6f035ab0907f6ed3e8fc29ff867d87d29930f13662e71fc4a2b1cb98192c; X_HTTP_TOKEN=d5f4986d37c406901391579461f5204004058ec73c; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1649751932; LGRID=20220412162600-e7fc153c-5f7a-4a98-8b5a-64deb84f97a5; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2217ca0ecfddc512-075219529da9d8-513c1f42-1049088-17ca0ecfddd423%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24os%22%3A%22Windows%22%2C%22%24browser%22%3A%22Chrome%22%2C%22%24browser_version%22%3A%2299.0.4844.74%22%7D%2C%22%24device_id%22%3A%2217ca0ecfddc512-075219529da9d8-513c1f42-1049088-17ca0ecfddd423%22%7D', 'Host': 'www.lagou.com', 'Referer': 'https://www.lagou.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55' }
注意:因为每个人的IP不同所以每个人的Cookie肯定是不一样的,具体的小伙伴们因自己的情况而定,请不要直接复制小编哦。
2.2 获取数据
2.2.1 第一版爬取
这一部分小编直接贴代码啦!
#encoding=utf-8#导入requests模块importrequestsurl="https://www.lagou.com/wn/jobs?labelWords=&fromSearch=true&suginput=&kd=python"headers= { 'Cookie': 'PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; LGSID=20220412161649-181e69d0-cfb8-4004-895e-f6e91c067f6a; PRE_SITE=https%3A%2F%2Fwww.lagou.com; privacyPolicyPopup=false; _gid=GA1.2.1338185489.1649751410; TG-TRACK-CODE=index_search; __lg_stoken__=74667837daa94dc4815a15e5abcc6d9d6bf9378cf0f87cf07f1cddc90c731b5dbffd39e14b57d61f6f035ab0907f6ed3e8fc29ff867d87d29930f13662e71fc4a2b1cb98192c; X_HTTP_TOKEN=d5f4986d37c406901391579461f5204004058ec73c; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1649751932; LGRID=20220412162600-e7fc153c-5f7a-4a98-8b5a-64deb84f97a5; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2217ca0ecfddc512-075219529da9d8-513c1f42-1049088-17ca0ecfddd423%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24os%22%3A%22Windows%22%2C%22%24browser%22%3A%22Chrome%22%2C%22%24browser_version%22%3A%2299.0.4844.74%22%7D%2C%22%24device_id%22%3A%2217ca0ecfddc512-075219529da9d8-513c1f42-1049088-17ca0ecfddd423%22%7D', 'Host': 'www.lagou.com', 'Referer': 'https://www.lagou.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55' } response=requests.get(url=url, headers=headers) print(response.text)
运行效果如下。
不难发现,数据我们拿到了,但是页面结构很乱,十分不便于我们查看,可不可以让这些爬取下来的数据有结构的排列呢?所以爬取的第二版来啦。
2.2.2 第二版爬取
1、先将我们需要爬取的数据部分从爬下来的网页中抠下来,最后发现需要的数据包裹在<script id="__NEXT_DATA__" type="application/json"></script>这组标签。具体如下图所示。
#使用正则表达式将html中想要获取的内容截取出来html_data=re.findall('<script id="__NEXT_DATA__" type="application/json">(.*?)</script>', response.text)[0] #因得到的是字符串数据,所以需要使用json.loads()把字符串数据转成字典json_data=json.loads(html_data) #使用pprint模块,格式化输出字典数据 有一个展示的效果pprint.pprint(json_data)
具体效果显示如下。
第二版具体的代码在这里啦!
#encoding=utf-8importrequests#导入正则表达式模块importre#导入json模块,将从网页上拿到的字符串转变为json格式importjson#导入格式化输出模块importpprinturl="https://www.lagou.com/wn/jobs?labelWords=&fromSearch=true&suginput=&kd=python"headers= { 'Cookie': ' X_HTTP_TOKEN=d5f4986d37c406902538000561f5204004058ec73c; PRE_UTM=; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2F; _gat=1; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1650008388; LGSID=20220415153947-7e60ec2e-ee49-4c46-a118-4097fd6af7f3; PRE_HOST=cn.bing.com; PRE_SITE=https%3A%2F%2Fcn.bing.com%2F; TG-TRACK-CODE=index_search; LGRID=20220415153954-22a58f66-8c1b-4209-b1dc-459bc3aae3d3; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2217ca0ecfddc512-075219529da9d8-513c1f42-1049088-17ca0ecfddd423%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E8%87%AA%E7%84%B6%E6%90%9C%E7%B4%A2%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC%22%2C%22%24latest_referrer%22%3A%22https%3A%2F%2Fcn.bing.com%2F%22%2C%22%24os%22%3A%22Windows%22%2C%22%24browser%22%3A%22Chrome%22%2C%22%24browser_version%22%3A%2299.0.4844.74%22%7D%2C%22%24device_id%22%3A%2217ca0ecfddc512-075219529da9d8-513c1f42-1049088-17ca0ecfddd423%22%7D', 'Host': 'www.lagou.com', 'Referer': 'https://www.lagou.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55'} response=requests.get(url=url, headers=headers) #print(response.text)html_data=re.findall('<script id="__NEXT_DATA__" type="application/json">(.*?)</script>', response.text)[0] # print(html_data)#得到的是字符串数据 需要把字符串数据转成字典json_data=json.loads(html_data) # 把字符串(完整数据结构)转成字典# print(json_data)pprint.pprint(json_data) # 格式化输出字典数据 有一个展示的效果
2.3 解析数据
什么是解析数据呢?在2.2章节的最后我们让所有爬取下来的有效信息进行了格式化字典数据的一个输出展示效果。解析其实简单来说,就是从刚刚我们爬的这一堆数据里面,把一些我们需要的数据字段进行提取,比如提取:props、pageProps、initData、content、positionResult、result这些字段,提取的代码具体如下所示。
#字典取值 根据冒号左边得内容(键),提取冒号右边得对应得内容forindexinjson_data['props']['pageProps']['initData']['content']['positionResult']['result']: dit= { '职位名字': index['positionName'], '公司名字': index['companyFullName'], '工作城市': index['city'], '学历要求': index['education'], '经验要求': index['workYear'], '薪资待遇': index['salary'], '公司地址': index['positionAddress'], }
2.4 保存数据
到这一步小编选用的是导出为csv文件,各位小伙伴们,也可以选择导出为其他格式的文件哦!具体代码和解释如下所示。
#导入csv模块importcsvf=open('拉钩招聘信息.csv', mode='a', encoding='utf-8', newline='') csv_writer=csv.DictWriter( f, fieldnames=[ '职位名字', '公司名字', '工作城市', '学历要求', '经验要求', '薪资待遇', '公司地址''详情页' ] ) dit= {'2.3中的解析数据'} csv_writer.writeheader() #写表头csv_writer.writerow(dit) #将存在解析后的数据dit写入到csv中#下面是将每一条招聘信息的岗位职责写入到本地磁盘,并且分别生成.txt文件进行存放title=index['positionName'] +index['companyFullName'] title=re.sub(r'[\/?:"<>!]]', '', title) withopen('info\\'+title+'.txt', mode='w', encoding='utf-8') asf: f.write(job_info)
3、福利时刻:代码贴贴
最后全篇的爬取代码都在这里了,代码如下。
#encoding=utf-8importrequests#导入正则表达式模块importre#导入json模块,将从网页上拿到的字符串转变为json格式importjson#导入格式化输出模块importpprint#导入csv模块importcsvf=open('拉钩招聘信息.csv', mode='a', encoding='utf-8', newline='') csv_writer=csv.DictWriter( f, fieldnames=[ '职位名字', '公司名字', '工作城市', '学历要求', '经验要求', '薪资待遇', '公司地址''详情页' ] ) csv_writer.writeheader() #写表头url="https://www.lagou.com/wn/jobs?pn={page}&fromSearch=true&suginput=&kd=python"headers= { 'Cookie': '17ca0ecfddd423%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24os%22%3A%22Windows%22%2C%22%24browser%22%3A%22Chrome%22%2C%22%24browser_version%22%3A%2299.0.4844.74%22%7D%2C%22%24device_id%22%3A%2217ca0ecfddc512-075219529da9d8-513c1f42-1049088-17ca0ecfddd423%22%7D', 'Host': 'www.lagou.com', 'Referer': 'https://www.lagou.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55' } response=requests.get(url=url, headers=headers) #print(response.text)html_data=re.findall('<script id="__NEXT_DATA__" type="application/json">(.*?)</script>', response.text)[0] #print(html_data)#得到的是字符串数据 需要把字符串数据转成字典json_data=json.loads(html_data)#把字符串(完整数据结构)转成字典#print(json_data)pprint.pprint(json_data)#格式化输出字典数据 有一个展示的效果#字典取值 根据冒号左边得内容(键),提取冒号右边得对应得内容forindexinjson_data['props']['pageProps']['initData']['content']['positionResult']['result']: pprint.pprint(index) job_info=index['positionDetail'].replace('<br/>','').replace('<br>') #岗位职责href=f'https://www.lagou.com/wn/jobs/{index["positionId"]}.html'dit= { '职位名字': index['positionName'], '公司名字': index['companyFullName'], '工作城市': index['city'], '学历要求': index['education'], '经验要求': index['workYear'], '薪资待遇': index['salary'], '公司地址': index['positionAddress'], '详情页':href } csv_writer.writerow(dit) title=index['positionName'] +index['companyFullName'] title=re.sub(r'[\/?:"<>!]]', '', title) withopen('info\\'+title+'.txt', mode='w', encoding='utf-8') asf: f.write(job_info)
4、最后
以上的代码比较基础,小编在这提几个未实现的点:
- 没有实现翻页爬取
- 没有对IP进行封装,爬取数据过多,可能会被服务器识别为爬虫,从而将IP封掉,无法爬取。
- 没有进行数据格式化
那么以上这些点可爱的读者们你们发现了嘛?嗨嗨嗨,以上未实现的知识点都藏在后续的文章里咯!欢迎提出博客不足的地方,相互学习,共同成长!