您的位置:首页 > 其它

Pyhton爬虫实战 - 抓取BOSS直聘职位描述 和 数据清洗

2017-12-14 15:05 351 查看
Pyhton爬虫实战 - 抓取BOSS直聘职位描述 和 数据清洗

  

  零、致谢

  

  感谢BOSS直聘相对权威的招聘信息,使本人有了这次比较有意思的研究之旅。

  

  由于爬虫持续爬取 www.bomaoyuLe.cn  网站,以致产生的服务器压力,本人深感歉意,并没有 DDoS 和危害贵网站的意思。

  

  2017-12-14 更新

  

  在跑了一夜之后,服务器 IP 还是被封了,搞得本人现在家里、公司、云服务器三线作战啊

  

  一、抓取详细的职位描述信息

  

  1.1 前提数据

  

  这里需要知道页面的 id 才能生成详细的链接,在 Python爬虫框架Scrapy实战 - 抓取BOSS直聘招聘信息 中,我们已经拿到招聘信息的大部分信息,里面有个 pid 字段就是用来唯一区分某条招聘,并用来拼凑详细链接的。

  

  是吧,明眼人一眼就看出来了。

  

  1.2 详情页分析

  

  详情页如下图所示

  

  P2

  

  在详情页中,比较重要的就是职位描述和工作地址这两个

  

  由于在页面代码中岗位职责和任职要求是在一个 div 中的,所以在抓的时候就不太好分,后续需要把这个连体婴儿,分开分析。

  

  1.3 爬虫用到的库

  

  使用的库有

  

  requests

  

  BeautifulSoup4

  

  pymongo

  

  对应的安装文档依次如下,就不细说了

  

  安装 Requests - Requests 2.18.1 文档

  

  安装 Beautiful Soup - Beautiful Soup 4.2.0 文档

  

  PyMongo安装使用笔记

  

  1.4 Python 代码

  

  """

  

  @author: jtahstu

  

  @contact: root@jtahstu.com

  

  @site: http://www.jtahstu.com
  

  @time: 2017/12/10 00:25

  

  """

  

  # -*- coding: utf-8 -*-

  

  import requests

  

  from bs4 import BeautifulSoup

  

  import time

  

  from pymongo import MongoClient

  

  headers = {

  

  'x-devtools-emulate-network-conditions-client-id': "5f2fc4da-c727-43c0-aad4-37fce8e3ff39",

  

  'upgrade-insecure-requests': "1",

  

  'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36",

  

  'accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",

  

  'dnt': "1",

  

  'accept-encoding': "gzip, deflate",

  

  'accept-language': "zh-CN,zh;q=0.8,en;q=0.6",

  

  'cookie': "__c=1501326829; lastCity=101020100; __g=-; __l=r=https%3A%2F%2Fwww.google.com.hk%2F&l=%2F; __a=38940428.1501326829..1501326829.20.1.20.20; Hm_lvt_194df3105ad7148dcf2b98a91b5e727a=1501326839; Hm_lpvt_194df3105ad7148dcf2b98a91b5e727a=1502948718;
__c=1501326829; lastCity=101020100; __g=-; Hm_lvt_194df3105ad7148dcf2b98a91b5e727a=1501326839; Hm_lpvt_194df3105ad7148dcf2b98a91b5e727a=1502954829; __l=r=https%3A%2F%2Fwww.google.com.hk%2F&l=%2F; __a=38940428.1501326829..1501326829.21.1.21.21",

  

  'cache-control': "no-cache",

  

  'postman-token': "76554687-c4df-0c17-7cc0-5bf3845c9831"

  

  }

  

  conn = MongoClient('127.0.0.1', 27017)

  

  db = conn.iApp  # 连接mydb数据库,没有则自动创建

  

  def init():

  

  items = db.jobs_php.find().sort('pid')

  

  for item in items:

  

  if 'detail' in item.keys(): # 在爬虫挂掉再此爬取时,跳过已爬取的行

  

  continue

  

  detail_url = "https://www.zhipin.com/job_detail/%s.html?ka=search_list_1" % item['pid']

  

  print(detail_url)

  

  html = requests.get(detail_url, headers=headers)

  

  if html.status_code != 200: # 爬的太快网站返回403,这时等待解封吧

  

  print('status_code is %d' % html.status_code)

  

  break

  

  soup = BeautifulSoup(html.text, "html.parser")

  

  job = soup.select(".job-sec .text")

  

  if len(job) < 1:

  

  continue

  

  item['detail'] = job[0].text.strip()  # 职位描述

  

  location = soup.select(".job-sec .job-location")

  

  item['location'] = location[0].text.strip()  # 工作地点

  

  item['updated_at'] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())  # 实时爬取时间

  

  res = save(item) # 保存数据

  

  print(res)

  

  time.sleep(40) # 停停停

  

  # 保存数据到 MongoDB 中

  

  def save(item):

  

  return db.jobs_php.update_one({"_id": item['_id']}, {"$set": item})

  

  if __name__ == "__main__":

  

  init()

  

  代码 easy,初学者都能看懂。

  

  1.5 再啰嗦几句

  

  在 上一篇文章 中只是爬了 上海-PHP 近300条数据,后续改了代码,把12个城市的 PHP 相关岗位的数据都抓下来了,有3500+条数据,慢慢爬吧,急不来。

  

  像这样

  

  P7

  

  P8

  

  二、数据清洗

  

  2.1 校正发布日期

  

  "time" : "发布于03月31日",

  

  "time" : "发布于昨天",

  

  "time" : "发布于11:31",

  

  这里拿到的都是这种格式的,所以简单处理下

  

  import datetime

  

  from pymongo import MongoClient

  

  db = MongoClient('127.0.0.1', 27017).iApp

  

  def update(data):

  

  return db.jobs_php.update_one({"_id": data['_id']}, {"$set": data})

  

  # 把时间校正过来

  

  def clear_time():

  

  items = db.jobs_php.find({})

  

  for item in items:

  

  if not item['time'].find('布于'):

  

  continue

  

  item['time'] = item['time'www.xinbeiyule.cn].replace("发布于", "2017-")

  

  item['time'] = item[www.078881.cn  'time'].replace("月", "-")

  

  item['time'] = item['time'].replace("日", "")

  

  if item['time'].find("昨天") > 0:

  

  item['time'] = str(datetime.date.today() - datetime.timedelta(days=1))

  

  elif item['time'].find("www.yitiali.com :") > 0:

  

  item['time'] = str(www.yinfenyule.com datetime.date.today())

  

  update(item)

  

  print('ok')

  

  2.2 校正薪水以数字保存

  

  "salary" : "5K-12K",

  

  #处理成下面的格式

  

  "salary" : {

  

  "low" : 5000,

  

  "high" : 12000,

  

  "avg" : 8500.0

  

  },

  

  # 薪水处理成数字

  

  def clear_salary():

  

  items = db.jobs_php.find({})

  

  for item in items:

  

  if type(item['salary']) == type({}):

  

  continue

  

  salary_list = item['salary'].replace("K", "000").split("-")

  

  salary_list = [int(x) for x in salary_list]

  

  item['salary'] = {

  

  'low': salary_list[0],

  

  'high': salary_list[1],

  

  'avg': (salary_list[0] + salary_list[1]) / 2

  

  }

  

  update(item)

  

  print('ok')

  

  2.3 根据 工作经验年限 划分招聘等级

  

  # 设置招聘的水平

  

  def set_level():

  

  items = db.jobs_php.find({})

  

  for item in items:

  

  if item['workYear'] == '应届生':

  

  item['level'] = 1

  

  elif item['workYear'] == '1年以内':

  

  item['level'] = 2

  

  elif item['workYear'] == '1-3年':

  

  item['level'] = 3

  

  elif item['workYear'] == '3-5年':

  

  item['level'] = 4

  

  elif item['workYear'] == '5-10年':

  

  item['level'] = 5

  

  elif item['workYear'] == '10年以上':

  

  item['level'] = 6

  

  elif item['workYear'] == '经验不限':

  

  item['level'] = 10

  

  update(item)

  

  print('ok')

  

  这里有点坑的就是,一般要求经验不限的岗位,需求基本都写在任职要求里了,所以为了统计的准确性,这个等级的数据,后面会被舍弃掉。

  

  2017-12-14 更新:

  

  从后续的平均数据来看,这里的经验不限,一般要求的是1-3年左右,但是还是建议舍弃掉。

  

  2.4 区分开<岗位职责>和<任职要求>

  

  对于作者这个初学者来说,这里还没有什么好的方法,知道的同学,请务必联系作者,联系方式在个人博客里

  

  so , i'm sorry.

  

  为什么这两个不好划分出来呢?

  

  因为这里填的并不统一,可以说各种花样,有的要求在前,职责在后,有的又换个名字区分。目前看到的关于要求的有['任职条件', '技术要求', '任职要求', '任职资格', '岗位要求']这么多说法。然后顺序还不一样,有的要求在前,职责在后,有的又反之。

  

  举个栗子

  

  会基本的php编程!能够修改简单的软件!对云服务器和数据库能够运用!懂得微信公众账号对接和开放平台对接!我们不是软件公司,是运营公司!想找好的公司学习的陕西基本没有,要到沿海城市去!但是我们是实用型公司,主要是软件应用和更适合大众!

  

  啥也不说的,这里可以认为这是一条脏数据了。

  

  不行,再举个栗子

  

  PHP中级研发工程师(ERP/MES方向)

  

  1、计算机或相关学科本科或本科以上学历;

  

  2、php和Java script的开发经验。

  

  3、Linux和MySQL数据库的开发经验;

  

  5、有ERP、MES相关开发经验优先;

  

  6、英语的读写能力;

  

  7、文化的开放性;

  

  我们提供

  

  1、有趣的工作任务;

  

  2、多元的工作领域;

  

  3、与能力相关的收入;

  

  4、年轻、开放并具有创造力的团队和工作氛围;

  

  5、不断接触最新科技(尤其是工业4.0相关);

  

  6、可适应短期出差(提供差补);

  

  这个只有要求,没职责,还多了个提供,我乐个趣 ╮(╯▽╰)╭

  

  所以,气的想骂人。

  

  ok ,现在我们的数据基本成这样了

  

  {

  

  "_id" : ObjectId("5a30ad2068504386f47d9a4b"),

  

  "city" : "苏州",

  

  "companyShortName" : "蓝海彤翔",

  

  "companySize" : "100-499人",

  

  "education" : "本科",

  

  "financeStage" : "B轮",

  

  "industryField" : "互联网",

  

  "level" : 3,

  

  "pid" : "11889834",

  

  "positionLables" : [

  

  "PHP",

  

  "ThinkPHP"

  

  ],

  

  "positionName" : "php研发工程师",

  

  "salary" : {

  

  "avg" : 7500.0,

  

  "low" : 7000,

  

  "high" : 8000

  

  },

  

  "time" : "2017-06-06",

  

  "updated_at" : "2017-12-13 18:31:15",

  

  "workYear" : "1-3年",

  

  "detail" : "1、处理landcloud云计算相关系统的各类开发和调研工作;2、处理coms高性能计算的各类开发和调研工作岗位要求:1、本科学历,两年以上工作经验,熟悉PHP开发,了解常用的php开发技巧和框架;2、了解C++,python及Java开发;3、有一定的研发能力和钻研精神;4、有主动沟通能力和吃苦耐劳的精神。",

  

  "location" : "苏州市高新区科技城锦峰路158号101park8幢"

  

  }

  

  由于还没到数据展示的时候,所以现在能想到的就是先这样处理了

  

  项目开源地址:http://git.jtahstu.com/jtahstu/Scrapy_zhipin

  

  三、展望和设想

  

  首先这个小玩意数据量并不够多,因为爬取时间短,站点唯一,再者广度局限在 PHP 这一个岗位上,以致存在一定的误差。

  

  所以为了数据的丰富和多样性,这个爬虫是一定要持续跑着的,至少要抓几个月的数据才算可靠吧。

  

  然后准备再去抓下拉勾网的招聘数据,这也是个相对优秀的专业 IT 招聘网站了,数据也相当多,想当初找实习找正式工作,都是在这两个 APP 上找的,其他的网站几乎都没看。

  

  最后,对于科班出身的学弟学妹们,过来人说一句,编程相关的职业就不要去志连、钱尘乌
9960
有、five eight桐城了,好吗?那里面都发的啥呀,看那些介绍心里没点数吗?

  

  四、help

  

  这里完全就是作者本人依据个人微薄的见识,主观臆断做的一些事情,所以大家有什么点子和建议,都可以联系作者,多交流交流嘛。

  

  后续会公开所有数据,大家自己可以弄着玩玩吧。

  

  我们太年轻,以致都不知道以后的时光,竟然那么长,长得足够让我们把一门技术研究到顶峰,乱花渐欲迷人眼,请不要忘了根本好吗。

  

  生活总是让我们遍体鳞伤,但到后来,那些受伤的地方一定会变成我们最强壮的地方。 —海明威 《永别了武器》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: