• 【拉勾网职位需求信息爬虫】技能长尾关键词抓取——看看你是否满足企业技能需求


    写在前面

    不同的语言,有它们各自擅长的应用场景,选择一门适合自己的语言需要勇气与毅力。

    而当你下定决心要在甄选的语言上一条道走到黑的时候,孰不知,选择才刚刚开始。

    一门编程语言往往有许多分支,每一个分支都需要掌握不同的技能,我们时常会感到困惑:怎么才能较为准确的分配技能点?

    需求决定选择,从招聘方的角度来观察,看看我们未来的金主需要现在的你我掌握什么技能,或许能够从繁多的技术分支中受到启发:

    这次练习的题目是通过Python抓取拉勾网的招聘详情页,并筛选其中的技能关键词,存储到excel中。

    一、获取职位需求数据

    通过观察可以发现,拉勾网的职位页面详情是由http://www.lagou.com/jobs/+*****(PositionId).html组成,而PositionId可以通过分析Json的XHR获得。而红框里的职位描述内容是我们要抓取的数据。


    知道了数据的源头,接下来就按照常规步骤包装Headers,提交FormData来获取反馈数据。

    获取PositionId列表所在页面:

     1 # 获取职位的查询页面(参数分别为网址,当前页面数,关键词)
     2 def get_page(url, pn, keyword):
     3     headers = {
     4         'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
     5                       'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
     6         'Host': 'www.lagou.com',
     7         'Connection': 'keep-alive',
     8         'Origin': 'http://www.lagou.com'
     9         }
    10     if pn == 1:
    11         boo = 'true'
    12     else:
    13         boo = 'false'
    14     # 通过页面分析,发现浏览器提交的FormData包括以下参数
    15     data = parse.urlencode([
    16         ('first', boo),
    17         ('pn', pn),
    18         ('kd', keyword)
    19         ])
    20     req = request.Request(url, headers=headers)
    21     page = request.urlopen(req, data=data.encode('utf-8')).read()
    22     page = page.decode('utf-8')
    23     return page

    通过Json获取PositionId:

    1 # 获取所需的岗位id,每一个招聘页面详情都有一个所属的id索引
    2 def read_id(page):
    3     tag = 'positionId'
    4     page_json = json.loads(page)
    5     page_json = page_json['content']['result']
    6     company_list = []
    7     for i in range(15):
    8         company_list.append(page_json[i].get(tag))
    9     return company_list

    合成目标url:

     1 # 获取职位页面,由PositionId和BaseUrl组合成目标地址
     2 def get_content(company_id):
     3     fin_url = r'http://www.lagou.com/jobs/%s.html' % company_id
     4     headers = {
     5         'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
     6                       'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
     7         'Host': 'www.lagou.com',
     8         'Connection': 'keep-alive',
     9         'Origin': 'http://www.lagou.com'
    10         }
    11     req = request.Request(fin_url, headers=headers)
    12     page = request.urlopen(req).read()
    13     content = page.decode('utf-8')
    14     return content

     二、对数据进行处理

    获取数据之后,需要对数据进行清洗,通过BeautifulSoup抓取的职位内容包含Html标签,需要让数据脱去这层“外衣”。

    1 # 获取职位需求(通过re来去除html标记),可以将职位详情单独存储
    2 def get_result(content):
    3     soup = Bs(content, 'lxml')
    4     job_description = soup.select('dd[class="job_bt"]') 
    5     job_description = str(job_description[0])
    6     rule = re.compile(r'<[^>]+>') 
    7     result = rule.sub('', job_description)
    8     return result

    现在得到的数据就是职位描述信息,我们要从职位信息当中筛选我们所关注的任职要求关键词。

    我们将这些关键词筛选出来,存储到List当中。经过对整个500+职位进行爬去,我们得到了职位技能关键词的总表。

    1 # 过滤关键词:目前筛选的方式只是选取英文关键词
    2 def search_skill(result):
    3     rule = re.compile(r'[a-zA-z]+')
    4     skill_list = rule.findall(result)
    5     return skill_list

    对关键词按照500+职位需求出现的频次进行排序,选取频次排序Top80的关键词,去除无效的关键词。

    1 # 对出现的关键词计数,并排序,选取Top80的关键词作为数据的样本
    2 def count_skill(skill_list):
    3     for i in range(len(skill_list)):
    4         skill_list[i] = skill_list[i].lower()
    5     count_dict = Counter(skill_list).most_common(80)
    6     return count_dict

    三、对数据进行存储和可视化处理

     1 # 对结果进行存储并生成Area图
     2 def save_excel(count_dict, file_name):
     3     book = xlsxwriter.Workbook(r'C:UsersAdministratorDesktop\%s.xls' % file_name)
     4     tmp = book.add_worksheet()
     5     row_num = len(count_dict)
     6     for i in range(1, row_num):
     7         if i == 1:
     8             tag_pos = 'A%s' % i
     9             tmp.write_row(tag_pos, ['关键词', '频次'])
    10         else:
    11             con_pos = 'A%s' % i
    12             k_v = list(count_dict[i-2])
    13             tmp.write_row(con_pos, k_v)
    14     chart1 = book.add_chart({'type': 'area'})
    15     chart1.add_series({
    16         'name': '=Sheet1!$B$1',
    17         'categories': '=Sheet1!$A$2:$A$80',
    18         'values':  '=Sheet1!$B$2:$B$80'
    19     })
    20     chart1.set_title({'name': '关键词排名'})
    21     chart1.set_x_axis({'name': '关键词'})
    22     chart1.set_y_axis({'name': '频次(/次)'})
    23     tmp.insert_chart('C2', chart1, {'x_offset': 25, 'y_offset': 10})

    这就是抓取之后的数据可视化展示。

    附上源码

      1 #! -*-coding:utf-8 -*-
      2 '''
      3 Function:计算拉勾网编程语言的关键词排名
      4 Author:蘭兹
      5 '''
      6 
      7 
      8 from urllib import request, parse
      9 from bs4 import BeautifulSoup as Bs
     10 from collections import Counter
     11 import lxml
     12 import json
     13 import datetime
     14 import xlsxwriter
     15 import re
     16 
     17 starttime = datetime.datetime.now()
     18 
     19 url = r'http://www.lagou.com/jobs/positionAjax.json?city=%E5%8C%97%E4%BA%AC'
     20 
     21 keyword = input('请输入您所需要查找的关键词 : ')
     22 
     23 
     24 # 获取职位的查询页面(参数分别为网址,当前页面数,关键词)
     25 def get_page(url, pn, keyword):
     26     headers = {
     27         'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
     28                       'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
     29         'Host': 'www.lagou.com',
     30         'Connection': 'keep-alive',
     31         'Origin': 'http://www.lagou.com'
     32         }
     33     if pn == 1:
     34         boo = 'true'
     35     else:
     36         boo = 'false'
     37     # 通过页面分析,发现浏览器提交的FormData包括以下参数
     38     data = parse.urlencode([
     39         ('first', boo),
     40         ('pn', pn),
     41         ('kd', keyword)
     42         ])
     43     req = request.Request(url, headers=headers)
     44     page = request.urlopen(req, data=data.encode('utf-8')).read()
     45     page = page.decode('utf-8')
     46     return page
     47 
     48 
     49 # 获取所需的岗位id,每一个招聘页面详情都有一个所属的id索引
     50 def read_id(page):
     51     tag = 'positionId'
     52     page_json = json.loads(page)
     53     page_json = page_json['content']['result']
     54     company_list = []
     55     for i in range(15):
     56         company_list.append(page_json[i].get(tag))
     57     return company_list
     58 
     59 
     60 # 获取当前招聘关键词的最大页数,大于30的将会被覆盖,所以最多只能抓取30页的招聘信息
     61 def read_max_page(page):
     62     page_json = json.loads(page)
     63     max_page_num = page_json['content']['totalPageCount']
     64     if max_page_num > 30:
     65         max_page_num = 30
     66     return max_page_num
     67 
     68 
     69 # 获取职位页面,由ositionId和BaseUrl组合成目标地址
     70 def get_content(company_id):
     71     fin_url = r'http://www.lagou.com/jobs/%s.html' % company_id
     72     headers = {
     73         'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
     74                       'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
     75         'Host': 'www.lagou.com',
     76         'Connection': 'keep-alive',
     77         'Origin': 'http://www.lagou.com'
     78         }
     79     req = request.Request(fin_url, headers=headers)
     80     page = request.urlopen(req).read()
     81     content = page.decode('utf-8')
     82     return content
     83 
     84 
     85 # 获取职位需求(通过re来去除html标记),可以将职位详情单独存储
     86 def get_result(content):
     87     soup = Bs(content, 'lxml')
     88     job_description = soup.select('dd[class="job_bt"]')
     89     job_description = str(job_description[0])
     90     rule = re.compile(r'<[^>]+>')
     91     result = rule.sub('', job_description)
     92     return result
     93 
     94 
     95 # 过滤关键词:目前筛选的方式只是选取英文关键词
     96 def search_skill(result):
     97     rule = re.compile(r'[a-zA-z]+')
     98     skill_list = rule.findall(result)
     99     return skill_list
    100 
    101 
    102 # 对出现的关键词计数,并排序,选取Top80的关键词作为数据的样本
    103 def count_skill(skill_list):
    104     for i in range(len(skill_list)):
    105         skill_list[i] = skill_list[i].lower()
    106     count_dict = Counter(skill_list).most_common(80)
    107     return count_dict
    108 
    109 
    110 # 对结果进行存储并生成Area图
    111 def save_excel(count_dict, file_name):
    112     book = xlsxwriter.Workbook(r'C:UsersAdministratorDesktop\%s.xls' % file_name)
    113     tmp = book.add_worksheet()
    114     row_num = len(count_dict)
    115     for i in range(1, row_num):
    116         if i == 1:
    117             tag_pos = 'A%s' % i
    118             tmp.write_row(tag_pos, ['关键词', '频次'])
    119         else:
    120             con_pos = 'A%s' % i
    121             k_v = list(count_dict[i-2])
    122             tmp.write_row(con_pos, k_v)
    123     chart1 = book.add_chart({'type': 'area'})
    124     chart1.add_series({
    125         'name': '=Sheet1!$B$1',
    126         'categories': '=Sheet1!$A$2:$A$80',
    127         'values':  '=Sheet1!$B$2:$B$80'
    128     })
    129     chart1.set_title({'name': '关键词排名'})
    130     chart1.set_x_axis({'name': '关键词'})
    131     chart1.set_y_axis({'name': '频次(/次)'})
    132     tmp.insert_chart('C2', chart1, {'x_offset': 25, 'y_offset': 10})
    133 
    134 ######################################################################################
    135 
    136 if __name__ == '__main__':
    137     max_pn = read_max_page(get_page(url, 1, keyword))  # 获取招聘页数
    138     fin_skill_list = []  # 关键词总表
    139     for pn in range(1, max_pn):
    140         print('***********************正在抓取第%s页信息***********************' % pn)
    141         page = get_page(url, pn, keyword)
    142         company_list = read_id(page)
    143         for company_id in company_list:
    144             content = get_content(company_id)
    145             result = get_result(content)
    146             skill_list = search_skill(result)
    147             fin_skill_list.extend(skill_list)
    148     print('***********************开始统计关键词出现频率***********************')
    149     count_dict = count_skill(fin_skill_list)
    150     print(count_dict)
    151     file_name = input(r'请输入要保存的文件名:')
    152     save_excel(count_dict, file_name)
    153     print('***********************正在保存到桌面***********************')
    154     endtime = datetime.datetime.now()
    155     time = (endtime - starttime).seconds
    156     print('总共用时:%s s' % time)

    30*15页的内容抓取需要花费2分多钟,相对来说还是有些慢,可以加入并行模块抓取数据。

    至此,拉勾网职位需求关键词的抓取就完成了。

    这个爬虫的目的就是为了抓取与编程语言相关的技能需求,大家可以通过排名靠前的关键词获知主流的框架或结构,避免遗漏。也可以通过长尾关键词来扩展自己的知识面。

    还有其他功能,大家可以自行开发,这里只做抛砖引玉之用,欢迎交流,转载请注明出处~ (^ _ ^)/~~

  • 相关阅读:
    学习笔记::有上下界的网络流
    zoj2314
    bzoj3261
    bzoj 1898
    bzoj4009
    bzoj4033
    bzoj3389
    bzoj2427
    uva 11825
    交换A与B值的四种方法
  • 原文地址:https://www.cnblogs.com/Lands-ljk/p/5444619.html
Copyright © 2020-2023  润新知