前程无忧爬取招聘信息

  • 介绍
    • 结果展示
    • 爬取的网页
    • 参数
    • 运行环境
    • 项目分析
      • 简单爬取
      • 多线程爬取
    • 数据的存储
      • csv
      • json
      • excel
      • mysql
    • 展示数据
    • 运行
    • 注意

介绍

该项目为课程期末作业,python三个月的学习成果展示,分析各地职位薪水的多少

结果展示

可视化结果:

excel结果:

json结果:

mysql:

源代码上传到Gitee:
https://gitee.com/ren-wenqing/PythonLearning.git

爬取的网页

https://search.51job.com/

参数

例:https://search.51job.com/list/090000,000000,0000,00,9,99,java,2,79.html
090000:城市代码
java:关键词
79:页数

具体参数可以自己在https://search.51job.com/中的搜索框中输入数据,观察浏览器地址的变化

运行环境

python:3.9.6
mysql:8.0.18
需要用到的库:

import collections
import json
import xlsxwriter as xlsxwriter
from utils import get_header
import requests
import queue
import threading
import os
import csv
import re
import pymysql
import matplotlib.pyplot as plt
from openpyxl import load_workbook
from faker import Faker

项目分析

简单爬取

直接向网页发送请求就可以获取到网页的源代码

req=requests.get(url=url, headers=self.header)

获取结果:

这里页面中的加载框一直是加载状态,并没有我们需要的数据,但爬取的网址在浏览器中却可以正常显示:

这是因为requests库无法解析js,页面源代码中可能包含招聘列表
查看页面源代码,可以看到有一行特别长的js

复制到解析工具:
都是我们需要的数据

这里直接用正则匹配最快

    def Spider(self):while not self.pagequeue.empty():url = self.pagequeue.get()print('正在爬取:{}'.format(url))req = requests.get(url, headers=get_header())req.encoding = 'gbk'response = req.content.decode('gbk')for i in range(1, 12):try:title = re.findall(r'"job_title":"(.*?)"', response)if title[0] == None:breakcompany_name = re.findall(r'"company_name":"(.*?)"', response)job_name = re.findall(r'"job_title":"(.*?)"', response)salary = re.findall(r'"providesalary_text":"(.*?)"', response)work_area = re.findall(r'"workarea_text":"(.*?)"', response)time = re.findall(r'"issuedate":"(.*?)"', response)company_type = re.findall(r'"companytype_text":"(.*?)"', response)company_hangye = re.findall(r'"companyind_text":"(.*?)"', response)detail = re.findall(r'"job_href":"(.*?)"', response)if len(salary[i]) != 0:salary = salary[i].replace('\\/', '/')salary=formatyue(salary)salary = formatqian(salary)salary=fomatpjun(salary)detail = detail[i].replace('\\/', '/')company_hangye = company_hangye[i].replace('\\/', '/')data = {"职位名称": job_name[i],"薪资(万/月)": salary,"公司名称": company_name[i],"工作地点": work_area[i],"发布时间": time[i],"公司链接": detail,"公司类型": company_type[i],"公司行业": company_hangye,}self.jobqueue.put(data)except:continue

这些是我debug后显示的数据,可以看到里面有很多转义“\”符号,需要剔除
我定义了三个方法对薪水解析统一格式,因为有的薪水是(千/月),有的是(万/月),还有的是(万/年)

def formatyue(str):sa = re.findall(r'(.*?)万/年', str)if len(sa) ==0:return strelse:sa1 = re.findall(r'(.*?)-(.*)', sa[0])saf = float(sa1[0][0])sal = float(sa1[0][1])saf = saf / 12sal = sal / 12str = "{}-{}万/月".format(round(saf, 1), round(sal, 1))return str
def formatqian(str):sa = re.findall(r'(.*?)千/月', str)if len(sa) ==0:return strelse:sa1 = re.findall(r'(.*?)-(.*)', sa[0])saf = float(sa1[0][0])sal = float(sa1[0][1])saf = saf / 10sal = sal / 10str = "{}-{}万/月".format(round(saf, 1), round(sal, 1))return strdef fomatpjun(str):sa = re.findall(r'(.*?)万/月', str)sa1 = re.findall(r'(.*?)-(.*)', sa[0])saf = float(sa1[0][0])+float(sa1[0][1])str = "{}".format(round(saf/2, 1))return str

多线程爬取

加快爬取速度

def run(self):thread_list = []for i in range(self.thread):t = threading.Thread(target=self.Spider)thread_list.append(t)for t in thread_list:t.setDaemon(True)t.start()for t in thread_list:t.join()

地址字段输入的是文字,但浏览器里是地址的数字代码,需要遍历地址对应的json
链接: https://js.51jobcdn.com/in/js/2016/layer/area_array_c.js.

def _get_city_code(self):url = 'https://js.51jobcdn.com/in/js/2016/layer/area_array_c.js'req = requests.get(url, headers=self.header).texta = req.find(self.city)return req[a - 9:a - 3]

数据的存储

csv

读取文件路径后,根据Spider方法里返回的列表,进行读取写入

 if os.path.exists(self.path):data_list = []self.path = os.path.join(self.path, 'save_list')while not self.jobqueue.empty():data_list.append(self.jobqueue.get())with open(os.path.join(self.path, 'info——job——{}——zone{}.csv'.format(self.keyword, self.city)), 'w',newline='', encoding='utf-8') as f:f_csv = csv.DictWriter(f, self.csv_header)f_csv.writeheader()f_csv.writerows(data_list)

json

这个是通过数据库排序输出获得的

import pymysql
def check():con = pymysql.connect(host='localhost', port=3306, user='root', password='0', database='qcwy', charset='utf8')cursor = con.cursor()sql = "SELECT * FROM `jobinfo` order by salary desc;"cursor.execute(sql)con.commit()results = cursor.fetchall()col_names = ['job_name','salary', 'company_name', 'work_area','company_hangye','detail']strs = {}for row in results:strs[row[0]] = dict(zip(col_names, row[2:]))cursor.close()con.close()result = json.dumps(strs)filename = 'gongsi.json'with open(filename, 'w') as file_obj:file_obj.write(result)

excel

import xlsxwriter as xlsxwriter
workbook = xlsxwriter.Workbook(r'C:\Users\SixStart\PycharmProjects\pythonProject1\期末\python.xlsx')
worksheet = workbook.add_worksheet()
worksheet.write("A1", "职位名称")
worksheet.write("B1", "薪资(万/月)")
worksheet.write("C1", "公司名称")
worksheet.write("D1", "工作地点")
worksheet.write("E1", "发布时间")
worksheet.write("F1", "公司链接")
worksheet.write("G1", "公司类型")
worksheet.write("H1", "公司行业")
worksheet.write("L1", "工资")
worksheet.write("M1", "次数")
salarylist = []
for i in range(1, len(data_list)):job_name = data_list[i]['职位名称']salary = data_list[i]['薪资(万/月)']company_name = data_list[i]['公司名称']work_area = data_list[i]['工作地点']time = data_list[i]['发布时间']detail = data_list[i]['公司链接']company_type = data_list[i]['公司类型']company_hangye = data_list[i]['公司行业']salarylist.append(salary)try:worksheet.write("A{}".format(i+1), job_name)worksheet.write("B{}".format(i+1), salary)worksheet.write("C{}".format(i+1), company_name)worksheet.write("D{}".format(i+1), work_area)worksheet.write("E{}".format(i+1), time)worksheet.write("F{}".format(i+1), detail)worksheet.write("G{}".format(i+1), company_type)worksheet.write("H{}".format(i+1), company_hangye)except:pass
workbook.close()

mysql

CREATE TABLE `jobinfo`  (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '信息编号',`job_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '职位名称',`salary` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '面议' COMMENT '薪资',`company_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '公司名称',`work_area` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '工作地点',`time` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '发布时间',`detail` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '公司链接',`company_type` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '公司类型',`company_hangye` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '公司行业',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 48561 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
import pymysql
con = pymysql.connect(host='localhost', port=3306, user='root', password='0', database='qcwy', charset='utf8')
cursor = con.cursor()
sql = "INSERT INTO `qcwy`.`jobinfo`(`id`, `job_name`, `salary`, `company_name`, `work_area`, `time`, `detail`, `company_type`, `company_hangye`) VALUES"
sqlv = "(null,'{}','{}','{}','{}','{}','{}','{}','{}');".format(job_name,salary,company_name,work_area, time, detail, company_type,company_hangye)
sql2 = sql + sqlv
try:cursor.execute(sql2)con.commit()
except:con.rollback()
cursor.close()
# 关闭连接
con.close()

展示数据

这个是和爬取分开的,所以重新打开了excel表读取(毕竟不能每次运行都一次爬几百个网页,防止我人无了)

import matplotlib.pyplot as plt
from openpyxl import load_workbook
def showpicuure():salarymoneylist = []salarycountlist = []# 读取文件wb = load_workbook('python.xlsx')ws = wb.active# 获取表中L列,L列为薪水从低到高排列for col in ws['L']:if isinstance(col.value, str):salarymoneylist.append(col.value)salarymoneylist.remove("工资")# 获取表M列,M列为该薪水的招聘数量for col in ws['M']:if isinstance(col.value, int):salarycountlist.append(col.value)#绘图plt.style.use('ggplot')customers_index = range(len(salarymoneylist))#设定图表长宽和像素fig = plt.figure(figsize=(15, 3), dpi=100)#设定图表所占区域ax1 = fig.add_subplot(1, 1, 1)#设定xy列,文字居中,图表颜色ax1.bar(customers_index, salarycountlist, align='center', color='darkblue')#设定文字在x轴底部,y轴左侧ax1.xaxis.set_ticks_position('bottom')ax1.yaxis.set_ticks_position('left')#设定x轴的元素plt.xticks(customers_index, salarymoneylist, rotation=0, fontsize='small')plt.xlabel('nums')plt.ylabel('salary')plt.title('Salary—Statistics—{}')plt.figure(dpi=80)plt.savefig('salary.png', bbox_inches='tight')plt.show()

运行

源代码在本博客开头哦,我博客上的这些当然是运行不了的,只能作为源代码的讲解

if __name__ == '__main__':key1 = input("请输入关键词")city1 = input("请输入城市")#爬虫zhaopin(keyword=key1, city=city1).run()#数据库正序输出jsoncheck()#读取excel生成图像showpicuure()

注意

不是每次都能运行成功,但是大部分都没什么问题,可能和网络质量有关,如果报错的gbk编码那些,就和网速有关,也可能是我引入的faker 库的问题

【python】前程无忧招聘——多线程、正则、伪造请求头、保存(excel\csv\json\mysql)、直条图展示相关推荐

  1. 08-Flutter移动电商实战-dio基础_伪造请求头获取数据

    08-Flutter移动电商实战-dio基础_伪造请求头获取数据 在很多时候,后端为了安全都会有一些请求头的限制,只有请求头对了,才能正确返回数据.这虽然限制了一些人恶意请求数据,但是对于我们聪明的程 ...

  2. firefox伪造请求头信息,模拟手机访问网站

    大概有两年没有去过chinaz的论坛了,昨天上去逛了逛.正好看到一个朋友在问百度是如何判断是不是手机登录的.有几个热心朋友回答的是js,我把百度首页的js看了下,没有找到一丝的手持设备判断的信息,我也 ...

  3. Firefox伪造请求头

    原文地址:http://justcoding.iteye.com/blog/2086233 Firefox黑客插件:http://blog.csdn.NET/stilling2006/article/ ...

  4. Python读取excel/csv表格并通过折线图可视化显示

    Python读取excel/csv表格并通过折线图可视化显示 写作背景 参数 使用figure()函数重新申请一个figure对象 注意,每次调用figure的时候都会重新申请一个figure对象 第 ...

  5. python伪造请求头x-forwarded-for的作用_Pyspider中给爬虫伪造随机请求头的实例

    Pyspider 中采用了 tornado 库来做 http 请求,在请求过程中可以添加各种参数,例如请求链接超时时间,请求传输数据超时时间,请求头等等,但是根据pyspider的原始框架,给爬虫添加 ...

  6. Python爬虫偷懒神器 — 快速构造请求头!

    我们在写爬虫构建请求的时候,不可避免地要添加请求头( headers ),一般来说,我们只要添加 user-agent 就能满足绝大部分需求了 但这并不是绝对的,有些请求单单添加一个 user-age ...

  7. Python爬虫——2.底层操作和请求头、请求代理以及cookie操作

    本文章此节主要讲解: ·爬虫程序urllib2模块底层操作: ·请求头的设置和添加: ·请求代理的种类和类型: ·关于cookie的操作(手动添加/程序自动获取) 一.爬虫底层操作和请求头的设置 1. ...

  8. Python爬虫requests模块在线生成请求头

    写爬虫的时候,请求头几乎是必写的,但是写起来有点繁琐,虽然不难,但是麻烦,所以这时候,一个自动生成请求头的方法就显得很重要了 在线生成请求头 https://curlconverter.com/ 使用 ...

  9. ajax伪造请求头设置失败,以及浏览器插件解决方案(待完善)

    w3c规定,当请求的header匹配以下不安全字符时,将被终止,具体参考如下: Accept-Charset Accept-Encoding Connection Content-Length Coo ...

最新文章

  1. INFO:在InstallShield中修改安装包压缩.cab包的大小
  2. python同时同步发送多个请求_python如何实现“发送一个请求,等待多个响应”的同步?...
  3. 限招2019应届计算机毕业生,2019年计算机专业应届毕业生自我鉴定
  4. VS2008 ,TFS2008破解序列号
  5. Hadoop之ReduceTask工作机制
  6. 张小龙做微信公众号APP,对自媒体是祸还是福?
  7. Python图像处理工具——PIL、opencv、matplotlib
  8. GPU Gems1 - 19 基于图像的光照(Image-Based Lighting)
  9. jQuery/javascript实现简单网页计算器
  10. x264 struct学习 1
  11. 西部数码服务器绑定域名解析,中国数据域名如何修改DNS设置方法
  12. 移动开发—媒体查询(Media Query)
  13. MySql的事务操作与演示样例
  14. python办公自动化案例-用python进行办公自动化都需要学习什么知识呢?
  15. 前端面试之那些稀奇古怪的问题
  16. 第八章 linux磁盘与文件系统管理g
  17. jdy视频直播流采集分析
  18. keil安装、注册及pack包安装
  19. 基于ASP.NET+SQL Server实现(Web)企业进销存管理系统【100010296】
  20. 动态规划----最长子序列

热门文章

  1. 基于JAVA校园生活信息服务平台计算机毕业设计源码+系统+数据库+lw文档+部署
  2. 【Python 数据科学】聚合apply和agg
  3. Python3环境通过Pip install安装mitmproxy
  4. 计算机中office是应用软件吗,计算机应用中Office办公软件的教学方法
  5. 如何巧妙运用技巧涨粉
  6. 数商云石油化工行业B2B集采平台解决方案:提高采购议价能力,规范化采购流程
  7. 智能、人机融合智能和深度态势感知
  8. 使用HBase Coprocessor
  9. 将磁盘空间转移给其他盘(分出新磁盘卷、合并空闲磁盘卷)
  10. window location href跳转无效