zoukankan      html  css  js  c++  java
  • Python爬取Boss直聘,帮你获取全国各类职业薪酬榜

    前言

    本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。

    作者: 王翔 清风Python

    PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取

    http://note.youdao.com/noteshare?id=3054cce4add8a909e784ad934f956cef

    爬虫面临的问题

    • 不再是单纯的数据一把抓

    多数的网站还是请求来了,一把将所有数据塞进去返回,但现在更多的网站使用数据的异步加载,爬虫不再像之前那么方便

    很多人说js异步加载与数据解析,爬虫可以做到啊,恩是的,无非增加些工作量,那是你没遇到牛逼的前端,多数的解决办法只能靠渲染浏览器抓取,效率低下,接着往下走

    • 千姿百态的登陆验证

    从12306的说说下面哪个糖是奶糖,到现在各大网站的滑动拼图、汉子点击解锁,这些操作都是在为了阻止爬虫的自动化运行。

    你说可以先登录了复制cookie,但cookie也有失效期吧?

    • 反爬虫机制

    何为反爬虫?犀利的解释网上到处搜,简单的逻辑我讲给你听。你几秒钟访问了我的网站一千次,不好意思,我把你的ip禁掉,一段时间你别来了。

    很多人又说了,你也太菜了吧,不知道有爬虫ip代理池的开源项目IPProxys吗?那我就呵呵了,几个人真的现在用过免费的ip代理池,你去看看现在的免费代理池,有几个是可用的!

    再说了,你通过IPProxys代理池,获取到可用的代理访问人家网站,人家网站不会用同样的办法查到可用的代理先一步封掉吗?然后你只能花钱去买付费的代理

    • 数据源头封锁

    平时大家看的什么爬爬豆瓣电影网站啊,收集下某宝评论啊....这些都是公开数据。但现在更多的数据逐步走向闭源化。数据的价值越来越大,没有数据获取的源头,爬虫面临什么问题?

    上面说了一堆的爬虫这不好那不好,结果我今天发的文章确是爬虫的,自己打自己的脸? 其实我只是想说说网站数据展示与分析的技巧...恰巧Boss直聘就做的很不错。怎么不错?一点点分析...

    • 数据共享

    先来看一张图

    在这里插入图片描述

    我选择黑龙江省的大兴安岭,去看看那里有招聘python的没,多数系统查询不到数据就会给你提示未获取到相关数据,但Boss直聘会悄悄地吧黑龙江省的python招聘信息给你显示处理,够鸡~贼。

    • 数据限制

    大兴安岭没有搞python的,那我们去全国看看吧:

    在这里插入图片描述

    这里差一点就把我坑了,我开始天真的以为,全国只有300条(一页30条,共10也)python招聘信息。 然后我回过头去看西安的,也只有10页,然后想着修改下他的get请求parameters,没卵用。

    这有啥用?仔细想...一方面可以做到放置咱们爬虫一下获取所有的数据,但这只是你自作多情,这东西是商机!

    每天那么多的商家发布招聘信息,进入不了top100,别人想看都看不到你的消息,除非搜索名字。那么如何排名靠前?答案就是最后俩字,靠钱。你是Boss直聘的会员,你发布的就会靠前....

    • 偷换概念

    依旧先看图:

    在这里插入图片描述

    我搜索的是ruby,你资料不够,其他来凑....

    • ip解析

    老套路,再来看一张图:

    在这里插入图片描述

    Boss直聘的服务器里,留着我的痕迹,多么骄傲的事情啊。你们想不想和我一样?只需要3秒钟.... 三秒钟内你的访问量能超过1000,妥妥被封!

    那么我们该怎么办

    • 设置不同的User-Agent

    使用pip install fake-useragent安装后获取多种User-Agent,但其实本地保存上几十个,完全够了....

    • 不要太夯(大力)

    适当的减慢你的速度,别人不会觉得是你菜....别觉得一秒爬几千比一秒爬几百的人牛逼(快枪手子弹打完的早....不算开车吧?)。

    • 购买付费的代理

    为什么我跳过了说免费的代理?因为现在搞爬虫的人太多了,免费的基本早就列入各大网站的黑名单了。

    所以解析到的原始数据如下:

    在这里插入图片描述

    先来看看python的薪酬榜:

    在这里插入图片描述

    看一下西安的排位,薪资平均真的好低.....

    代码

      1 import requests
      2 from bs4 import BeautifulSoup
      3 import csv
      4 import random
      5 import time
      6 import argparse
      7 from pyecharts.charts import Line
      8 import pandas as pd
      9  10  11 class BossCrawler:
     12     def __init__(self, query):
     13  14         self.query = query
     15         self.filename = 'boss_info_%s.csv' % self.query
     16         self.city_code_list = self.get_city()
     17         self.boss_info_list = []
     18         self.csv_header = ["city", "profession", "salary", "company"]
     19  20     @staticmethod
     21     def getheaders():
     22         user_list = [
     23             "Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16",
     24             "Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14",
     25             "Mozilla/5.0 (Windows NT 6.0; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 12.14",
     26             "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14",
     27             "Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02",
     28             "Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00",
     29             "Opera/9.80 (Windows NT 5.1; U; zh-sg) Presto/2.9.181 Version/12.00",
     30             "Opera/12.0(Windows NT 5.2;U;en)Presto/22.9.168 Version/12.00",
     31             "Opera/12.0(Windows NT 5.1;U;en)Presto/22.9.168 Version/12.00",
     32             "Mozilla/5.0 (Windows NT 5.1) Gecko/20100101 Firefox/14.0 Opera/12.0",
     33             "Opera/9.80 (Windows NT 6.1; WOW64; U; pt) Presto/2.10.229 Version/11.62",
     34             "Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.10.229 Version/11.62",
     35             "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
     36             "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; de) Presto/2.9.168 Version/11.52",
     37             "Opera/9.80 (Windows NT 5.1; U; en) Presto/2.9.168 Version/11.51",
     38             "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; de) Opera 11.51",
     39             "Opera/9.80 (X11; Linux x86_64; U; fr) Presto/2.9.168 Version/11.50",
     40             "Opera/9.80 (X11; Linux i686; U; hu) Presto/2.9.168 Version/11.50",
     41             "Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11",
     42             "Opera/9.80 (X11; Linux i686; U; es-ES) Presto/2.8.131 Version/11.11",
     43             "Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/5.0 Opera 11.11",
     44             "Opera/9.80 (X11; Linux x86_64; U; bg) Presto/2.8.131 Version/11.10",
     45             "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10",
     46             "Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.8.131 Version/11.10",
     47             "Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1",
     48             "Opera/9.80 (X11; Linux x86_64; U; Ubuntu/10.10 (maverick); pl) Presto/2.7.62 Version/11.01",
     49             "Opera/9.80 (X11; Linux i686; U; ja) Presto/2.7.62 Version/11.01",
     50             "Opera/9.80 (X11; Linux i686; U; fr) Presto/2.7.62 Version/11.01",
     51             "Opera/9.80 (Windows NT 6.1; U; zh-tw) Presto/2.7.62 Version/11.01",
     52             "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.7.62 Version/11.01",
     53             "Opera/9.80 (Windows NT 6.1; U; sv) Presto/2.7.62 Version/11.01",
     54             "Opera/9.80 (Windows NT 6.1; U; en-US) Presto/2.7.62 Version/11.01",
     55             "Opera/9.80 (Windows NT 6.1; U; cs) Presto/2.7.62 Version/11.01",
     56             "Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.7.62 Version/11.01",
     57             "Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.7.62 Version/11.01",
     58             "Opera/9.80 (Windows NT 5.1; U;) Presto/2.7.62 Version/11.01",
     59             "Opera/9.80 (Windows NT 5.1; U; cs) Presto/2.7.62 Version/11.01",
     60             "Mozilla/5.0 (Windows NT 6.1; U; nl; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01",
     61             "Mozilla/5.0 (Windows NT 6.1; U; de; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01",
     62             "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; de) Opera 11.01",
     63             "Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00",
     64             "Opera/9.80 (X11; Linux i686; U; it) Presto/2.7.62 Version/11.00",
     65             "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.6.37 Version/11.00",
     66             "Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.7.62 Version/11.00",
     67             "Opera/9.80 (Windows NT 6.1; U; ko) Presto/2.7.62 Version/11.00",
     68             "Opera/9.80 (Windows NT 6.1; U; fi) Presto/2.7.62 Version/11.00",
     69             "Opera/9.80 (Windows NT 6.1; U; en-GB) Presto/2.7.62 Version/11.00",
     70             "Opera/9.80 (Windows NT 6.1 x64; U; en) Presto/2.7.62 Version/11.00",
     71             "Opera/9.80 (Windows NT 6.0; U; en) Presto/2.7.39 Version/11.00"
     72         ]
     73         user_agent = random.choice(user_list)
     74         headers = {'User-Agent': user_agent}
     75         return headers
     76  77     def get_city(self):
     78         headers = self.getheaders()
     79         r = requests.get("http://www.zhipin.com/wapi/zpCommon/data/city.json", headers=headers)
     80         data = r.json()
     81         return [city['code'] for city in data['zpData']['hotCityList'][1:]]
     82  83     def get_response(self, url, params=None):
     84         headers = self.getheaders()
     85         r = requests.get(url, headers=headers, params=params)
     86         r.encoding = 'utf-8'
     87         soup = BeautifulSoup(r.text, "lxml")
     88         return soup
     89  90     def get_url(self):
     91         for city_code in self.city_code_list:
     92             url = "https://www.zhipin.com/c%s/" % city_code
     93             self.per_page_info(url)
     94             time.sleep(10)
     95  96     def per_page_info(self, url):
     97         for page_num in range(1, 11):
     98             params = {"query": self.query, "page": page_num}
     99             soup = self.get_response(url, params)
    100             lines = soup.find('div', class_='job-list').select('ul > li')
    101             if not lines:
    102                 # 代表没有数据了,换下一个城市
    103                 return
    104             for line in lines:
    105                 info_primary = line.find('div', class_="info-primary")
    106                 city = info_primary.find('p').text.split(' ')[0]
    107                 job = info_primary.find('div', class_="job-title").text
    108                 # 过滤答非所谓的招聘信息
    109                 if self.query.lower() not in job.lower():
    110                     continue
    111                 salary = info_primary.find('span', class_="red").text.split('-')[0].replace('K', '')
    112                 company = line.find('div', class_="info-company").find('a').text.lower()
    113                 result = dict(zip(self.csv_header, [city, job, salary, company]))
    114                 print(result)
    115                 self.boss_info_list.append(result)
    116 117     def write_result(self):
    118         with open(self.filename, "w+", encoding='utf-8', newline='') as f:
    119             f_csv = csv.DictWriter(f, self.csv_header)
    120             f_csv.writeheader()
    121             f_csv.writerows(self.boss_info_list)
    122 123     def read_csv(self):
    124         data = pd.read_csv(self.filename, sep=",", header=0)
    125         data.groupby('city').mean()['salary'].to_frame('salary').reset_index().sort_values('salary', ascending=False)
    126         result = data.groupby('city').apply(lambda x: x.mean()).round(1)['salary'].to_frame(
    127             'salary').reset_index().sort_values('salary', ascending=False)
    128         print(result)
    129         charts_bar = (
    130             Line()
    131                 .set_global_opts(
    132                 title_opts={"text": "全国%s薪酬榜" % self.query})
    133                 .add_xaxis(result.city.values.tolist())
    134                 .add_yaxis("salary", result.salary.values.tolist())
    135         )
    136         charts_bar.render('%s.html' % self.query)
    137 138 139 if __name__ == '__main__':
    140     parser = argparse.ArgumentParser()
    141     parser.add_argument("-k", "--keyword", help="请填写所需查询的关键字")
    142     args = parser.parse_args()
    143     if not args.keyword:
    144         print(parser.print_help())
    145     else:
    146         main = BossCrawler(args.keyword)
    147         main.get_url()
    148         main.write_result()
    149         main.read_csv()
  • 相关阅读:
    ASP.NET Core 与 .NET Core 演变与基础概述
    Mac 下使用 brew 安装软件
    关于微信支付,支付宝支付与银联支付的异步消息状态
    keytab生成不了
    Exit code from container executor initialization is : 24 ExitCodeException exitCode=24: Configuration file ../etc/hadoop/container-executor.cfg not found.
    Connection broken for id 62, my id = 70, error =
    File system needs to be upgraded. You have version null and I want version 7
    virsh创建和恢复快照
    raw转qcow2
    Freemaker 自定义函数
  • 原文地址:https://www.cnblogs.com/Qqun821460695/p/11977178.html
Copyright © 2011-2022 走看看