招聘数据爬取、数据处理与可视化(v2--解析JS渲染页面)

更新说明

上一版本地址
由于爬取的原网站的变化,当前数据是在JavaScript中,浏览器会对JavaScript代码进行渲染,然后再呈现。然而,当我们通过爬虫程序获取数据时,爬虫程序并不能自动对HTML文件中的JavaScript代码进行渲染。因此,需要获取JS中数据进行解析。

程序说明

通过爬取“51job”获取招聘信息(以计算机软件为例),根据所获取数据分析领域相关工作职位需求,并通过可视化的方式展示分析行业就业情况(例如平均月薪、工作地点等)。

数据爬取

使用requests库请求网页内容,使用BeautifulSoup4正则表达库re解析网页。

观察网页结构

首先在爬取网页前,使用使用浏览器“开发者工具”,观察网页结构。
页面结构

页面解析

使用beautifulsoup解析页面,获取JS中所需数据:

soup.find_all('script')[7]

为了能够使用re解析获取内容,需要将内容转换为字符串:

results = str(soup.find_all('script')[7])

例如为了获取工作名,首先构造正则表达式:

pattern = re.compile(r'"job_name":"(.*?)"',re.MULTILINE|re.DOTALL)

然后查找所有的工作名:

job_names = pattern_job_name.findall(results)

为了方便获取所需字段,构造解析函数

def analysis(item,results):
    pattern = re.compile(item, re.I|re.M)
    result_list = pattern.findall(results)
    return result_list

将数据写入csv文件中

观察解析出的数据,例如公司名地址:

https:\/\/jobs.51job.com\/all\/co6371981.html

例如工作名:

Trade Ops(Contractor, Operations)

为了将数据写入csv文件中,首先需要将获得数据中的逗号','去除,因为其表示单元格的切换,然后还需去掉结果中的转义字符/
因此将获取的数据进行预处理:

def precess(item):
    return item.replace(',', ' ').replace('\\', '')

通过观察页面链接,爬取所有页面

查看第2页链接为:

https://search.51job.com/list/000000,000000,0000,00,9,99,%25E8%25AE%25A1%25E7%25AE%2597%25E6%259C%25BA,2,2.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=

第3页链接为:

https://search.51job.com/list/000000,000000,0000,00,9,99,%25E8%25AE%25A1%25E7%25AE%2597%25E6%259C%25BA,2,3.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=

仅改变了页面数字,因此可以构造如下模式,并使用循环,爬取所有页面:

url_pattern = "https://search.51job.com/list/000000,000000,0000,00,9,99,%25E8%25AE%25A1%25E7%25AE%2597%25E6%259C%25BA,2,{}.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare="
for i in range(1,2001):
    url = url_pattern.format(i)

爬虫程序完整代码

import time
import requests
from bs4 import BeautifulSoup
import os
import csv
import re

def analysis(item,results):
    pattern = re.compile(item, re.I|re.M)
    result_list = pattern.findall(results)
    return result_list

def precess(item):
    return item.replace(',', ' ').replace('\\', '')

#构建请求头
headers = {
    'User-Agent':'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0'
}
url_pattern = "https://search.51job.com/list/000000,000000,0000,00,9,99,%25E8%25AE%25A1%25E7%25AE%2597%25E6%259C%25BA,2,{}.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare="

if not os.path.exists("intro_job.csv"):
    #创建存储csv文件存储数据
    file = open('intro_job.csv', "w", encoding="utf-8-sig",newline='')
    csv_head = csv.writer(file)
    #表头
    header = ['job','company','place','salary','date','detail_url']
    csv_head.writerow(header)
    file.close()
    
for i in range(1,2001):
    #增加时延防止反爬虫
    time.sleep(5)
    url = url_pattern.format(i)
    response = requests.get(url=url, headers=headers)
    
    #声明网页编码方式,需要根据具体网页响应情况
    response.encoding = 'gbk'
    response.raise_for_status()
    soup = BeautifulSoup(response.text, 'html.parser')
    #pattern = re.compile(r"engine_search_result'(.*?)'",re.MULTILINE|re.DOTALL)
    results = str(soup.find_all('script')[7])
    job_names  = analysis(r'"job_name":"(.*?)"', results)
    company_names = analysis(r'"company_name":"(.*?)"', results)
    workarea_texts = analysis(r'"workarea_text":"(.*?)"', results)
    providesalary_texts = analysis(r'"providesalary_text":"(.*?)"', results)
    updatedates = analysis(r'"updatedate":"(.*?)"', results)
    job_hrefs = analysis(r'"job_href":"(.*?)"', results)
    for i in range(len(job_names)):
        with open('intro_job.csv', 'a+', encoding='utf-8-sig') as f:
            f.write(precess(job_names[i]) + ',' 
                    + precess(company_names[i]) + ',' 
                    + precess(workarea_texts[i]) + ',' 
                    + precess(providesalary_texts[i]) + ',' 
                    + precess(updatedates[i]) +',' 
                    + precess(job_hrefs[i]) + '\n')

爬取数据结果

展示部分爬取结果:
部分数据展示

数据及可视化

该部分参考之前博客

The end

Enjoying coding!

  • 19
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 43
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盼小辉丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值