爬虫-拉勾招聘需求词频分析

作者: 谦面客 | 来源:发表于2017-11-20 18:30 被阅读406次

    本文实现拉勾网的爬虫,抓取招聘需求,统计出的词频前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

    相关文章

      网友评论

      本文标题:爬虫-拉勾招聘需求词频分析

      本文链接:https://www.haomeiwen.com/subject/dnxbvxtx.html