写在前面:某日,公司想要招聘一个岗位的人员,想从招聘网上看看相关岗位的薪资及相关条件,于是就有了以下爬取过程。
这里以关键词 “基因” “近一个月内”作为条件爬取相关信息,打开猎聘网,输入 “基因”,选择近一个月内,结果如下:
当前显示的是第一页:
查看当前链接:发现规律不明显
https://www.liepin.com/zhaopin/?init=-1&headckid=181a371f3583bfee&flushckid=1&fromSearchBtn=2&pubTime=30&ckid=3d871f0122b3e6c9°radeFlag=0&curPage=0&sfrom=click-pc_homepage-centre_searchbox-search_new&key=%E5%9F%BA%E5%9B%A0&siTag=wpx05sEHOAKOTToVOh4zJw~fA9rXquZc5IkJpXC-Ycixw&d_sfrom=search_fp&d_ckId=cf67c27a6ce68af047a9752179e2d5d0&d_curPage=0&d_pageSize=40&d_headId=8551d000d99330889491c8d91023137d
点击第二页并查看第二页的链接:
https://www.liepin.com/zhaopin/?init=-1&headckid=181a371f3583bfee&fromSearchBtn=2&pubTime=30&ckid=43f135ffd04645b1°radeFlag=0&sfrom=click-pc_homepage-centre_searchbox-search_new&key=%E5%9F%BA%E5%9B%A0&siTag=wpx05sEHOAKOTToVOh4zJw~UoKQA1_uiNxxEb8RglVcHg&d_sfrom=search_fp&d_ckId=a7fac3c3df0712444f709570b349c883&d_curPage=0&d_pageSize=40&d_headId=8551d000d99330889491c8d91023137d&curPage=1
通过对比发现关键curpage=1表示的是第二页,那是不是将1改为相应的数字就找到了页码呢?为了证实猜想,我们多点开几个试一下,试过之后发现curpage=0表示第一页,curpage=2表示第三页,猜想正确!这样一来URL的构造就非常简单了,只需要更改url最后的数字即可。接下来就是确定一共有多少页,点击页码跳到最后发现一共有100页:
这样,URL的构造就很清晰了,如下:
url = 'https://www.liepin.com/zhaopin/?init=-1&headckid=181a371f3583bfee&fromSearchBtn=2&pubTime=30&ckid=27fda43c09cfd22a°radeFlag=0&sfrom=click-pc_homepage-centre_searchbox-search_new&key=%E5%9F%BA%E5%9B%A0&siTag=wpx05sEHOAKOTToVOh4zJw~UoKQA1_uiNxxEb8RglVcHg&d_sfrom=search_fp&d_ckId=72cb43ffd77e25f190635f45f4400ce0&d_curPage=0&d_pageSize=40&d_headId=8551d000d99330889491c8d91023137d&curPage='
for i in range(101):
url = url + 'i'
接下来就是获得具体的页面信息:检查网页元素发现每一条职位信息都在ul标签下的li标签中,于是我们可以通过xpath定位li标签
html = requests.get(url, headers = headers).text
mytree = lxml.etree.HTML(html)
postList = mytree.xpath('//ul[@class="sojob-list"]/li')
这样得到的是所有的li标签列表,现在我们来解决其中一个具体的li标签用以获得想要的内容:
从该结构中可以看到,我们想要的内容在li标签下的h3标签和p标签中,从而使用相应的xpath继续定位并提取内容:
postTitle = postList.xpath('.//div[@class="job-info"]/h3/a/text()')[0]
postInfo = postList.xpath('.//div[@class="job-info"]/p/span//text()')
postSalary = postInfo[0]
postEDU = postInfo[1]
postExperience = postInfo[2]
这样一来基本上就解决了一条职位信息的获取,一页的信息只需对li标签列表进行循环获取,而所有页面的信息只需对所有构造的url进行循环获取,最终将所有信息保存下来即可。
完整代码如下:
import csv
from time import sleep
import lxml
import requests
from lxml import etree
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36"}
url = 'https://www.liepin.com/zhaopin/?init=-1&headckid=181a371f3583bfee&fromSearchBtn=2&pubTime=30&ckid=27fda43c09cfd22a°radeFlag=0&sfrom=click-pc_homepage-centre_searchbox-search_new&key=%E5%9F%BA%E5%9B%A0&siTag=wpx05sEHOAKOTToVOh4zJw~UoKQA1_uiNxxEb8RglVcHg&d_sfrom=search_fp&d_ckId=72cb43ffd77e25f190635f45f4400ce0&d_curPage=0&d_pageSize=40&d_headId=8551d000d99330889491c8d91023137d&curPage='
def getPerPageInfo(url):
html = requests.get(url, headers = headers).text
mytree = lxml.etree.HTML(html)
postList = mytree.xpath('//ul[@class="sojob-list"]/li')
# print(postList)
for post in postList:
postTitle = post.xpath('.//div[@class="job-info"]/h3/a/text()')[0]
postInfo = post.xpath('.//div[@class="job-info"]/p/span//text()')
postSalary = postInfo[0]
postEDU = postInfo[1]
postExperience = postInfo[2]
infoList = [postTitle,postSalary,postEDU,postExperience]
# 将得到的数据用csv格式存储
writer.writerow(infoList) # writerows()会把单个字符写入到一个单元格中,而writerow()会把一个字符串写入一个单元格中
if __name__ == '__main__':
csvHeader = ['招聘岗位','薪酬','所需学历','工作经验']
with open('./猎聘网基因相关岗位信息.csv', 'a+', encoding='utf-8', errors='ignore', newline="") as f:
writer = csv.writer(f)
writer.writerow(csvHeader)
for i in range(101):
url = url + str(i)
getPerPageInfo(url)
sleep(0.5) # 每一页爬取时延迟一会,防止对别人服务器造成太大压力
总结:这个爬取过程比较简单,基本上没有遇到什么阻力,当然,这也跟我们爬去的内容简单有关系,如果想要爬去更多内容或者爬取更加智能化还需要修改很多地方,比如还要爬去详情页,相关的关键字不去手动输入通过分析后得到URL而是使用者输入关键字后url自动生成等等,这些都可以作为扩展进行联系。