本文实现拉勾网的爬虫,抓取招聘需求,统计出的词频前70的关键词,当然数量可以自己定,以深圳市的python招聘岗位为例。
1、爬虫老套路,分析浏览器请求,然后模仿之
先手动打开拉勾的招聘链接,进行搜索,观察浏览器的行为
https://www.lagou.com/zhaopin/
搜索python后页面显示很多职位信息,然后打开 chrome 开发者工具查看这个页面的response,发现响应中找不到岗位信息
查看开发者工具中的响应
这样看来就是用ajax来请求的数据了,把这个ajax请求找到,发现岗位信息都在这个响请求中,form data中的pn就是页码,kd是关键字
找到响应的ajax请求
于是模仿这个来发起请求,先获取第一页(这里有一个坑,如果请求头没有 Referer 字段,请求不到数据,反爬的常用手段,直接复制上面找到的请求中的就行)
import requests
import json
class LagouCrawl(object):
def __init__(self):
self.url = "https://www.lagou.com/jobs/positionAjax.json"
# 请求头
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36",
"Referer": "https://www.lagou.com/jobs/list_python"
}
# 查询字符串
self.params = {
"city": "深圳",
"needAddtionalResult": False,
"isSchoolJob": 0
}
# 表单数据
self.data = {
"first": True,
"pn": 1,
"kd": 'python'
}
def start_crawl(self):
response = requests.post(self.url, params=self.params, data=self.data, headers=self.headers)
data = response.content.decode('utf-8')
dict_data = json.loads(data)
print(dict_data)
if __name__ == '__main__':
spider = LagouCrawl()
spider.start_crawl()
这里得到一个 json 数据,里面有每条招聘的hr信息,招聘信息,我们需要的是以下的信息,都可以得到,以便于持续翻页得到所有的数据:
- 当前页的数量
- 总页数
- 符合条件的招聘条数
- 详情页的positionid,拼接出详情页url
整个数据比较长,只展示 positionId 的位置
部分json数据字段
拼接出详情页的url
def build_detail_url(self, data, num): # num 是一页的数量
for i in range(num):
position_id = data['content']['positionResult']['result'][i]['positionId']
url = INFO_URL % position_id
然后再访问详情页,通过 xpath 提取详情页内的需求文字(需要掌握xpath提取规则),下面的 info_text 就是提取出的文字
from lxml import etree
def parse_html(self, html):
obj_xpath = etree.HTML(html)
node = obj_xpath.xpath("//dd[@class='job_bt']")
info_node = node[0]
info_text = info_node.xpath("string(.)").strip()
return info_text
调用下面方法,得到的数据保存到 txt 中
def save_data(self, data):
with open('info.txt', 'a', encoding='utf-8') as f:
f.write(data)
这样得到的只是一页的,修改上面的代码把请求的页码做一个累加,爬取所有(连续爬取会出现问题,拉勾设置了访问频率,大概一分钟5次的样子,需要延时)
2、得到数据,利用它来干一些事情
用 jieba 分词读取所有内容进行分词,并使用 wordcloud 生成词频图,setting.py 设置一些频率高会影响结果的词与默认的停用词并集,一起过滤。
import jieba.analyse # 导入结巴分词
import numpy as np # numpy
from wordcloud import WordCloud, STOPWORDS # 词云工具和自带的的停用词
from PIL import Image # 图片处理
from setting import STOPWORD_NEW # 自定义了一个setting.py,过滤一些无关的词
def handle(filename, stopword):
with open(filename, 'r', encoding='utf-8') as f:
data = f.read()
wordlist = jieba.analyse.extract_tags(data, topK=70) # 分词,取前70
wordStr = " ".join(wordlist)
hand = np.array(Image.open('hand.jpg')) # 打开一张图片,词语以图片形状为背景分布
my_cloudword = WordCloud( # wordcloud参数配置
background_color = 'black', # 背景颜色
mask = hand, # 背景图片
max_words = 300, # 最大显示的字数
stopwords = stopword, # 停用词
max_font_size = 60, # 字体最大值
)
my_cloudword.generate(wordStr) # 生成图片
my_cloudword.to_file('wordcloud.png') # 保存
if __name__ == '__main__':
handle('python.txt', STOPWORDS | STOPWORD_NEW)
3、最后把整个程序再修改一下
- 用协程进行多任务(因为拉勾限制了爬取频率,中间大部分时间用来休眠了,并所以没起到作用,可以用代理池解决,这里没使用)
- 增加了拉勾所有城市的爬取
- 可以手动输入城市和关键字进行职位搜索
修改后目录结构如下:
目录结构
整个过程:爬虫启动时,开启两个协程,一个请求获取json数据,构建详情页url,扔进队列中,另一个从队列拿取url,爬岗位需求(这里可以用多个协程一起爬的,但拉勾访问频率限制了,只用了一个,中间休眠很久,很慢),用 queue.join() 阻塞主进程,当队列任务执行完后调用 HandleData 模块的方法,读取数据生成图,效果图如下。
词云效果
个人博客: 拉勾爬虫
附上代码,仅供参考: 拉勾招聘
END
网友评论