打造IP代理池,Python爬取Boss直聘,帮你获取全国各类职业薪酬榜
爬虫面临的问题
不再是单纯的数据一把抓
多数的网站还是请求来了,一把将所有数据塞进去返回,但现在更多的网站使用数据的异步加载,爬虫不再像之前那么方便
很多人说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()
打造IP代理池,Python爬取Boss直聘,帮你获取全国各类职业薪酬榜的更多相关文章
- Python爬取Boss直聘,帮你获取全国各类职业薪酬榜
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 王翔 清风Python PS:如有需要Python学习资料的小伙伴 ...
- Scrapy 爬取BOSS直聘关于Python招聘岗位
年前的时候想看下招聘Python的岗位有多少,当时考虑目前比较流行的招聘网站就属于boss直聘,所以使用Scrapy来爬取下boss直聘的Python岗位. 1.首先我们创建一个Scrapy 工程 s ...
- Python的scrapy之爬取boss直聘网站
在我们的项目中,单单分析一个51job网站的工作职位可能爬取结果不太理想,所以我又爬取了boss直聘网的工作,不过boss直聘的网站一次只能展示300个职位,所以我们一次也只能爬取300个职位. jo ...
- 用BeautifulSoup简单爬取BOSS直聘网岗位
用BeautifulSoup简单爬取BOSS直聘网岗位 爬取python招聘 import requests from bs4 import BeautifulSoup def fun(path): ...
- python3 爬取boss直聘职业分类数据(未完成)
import reimport urllib.request # 爬取boss直聘职业分类数据def subRule(fileName): result = re.findall(r'<p cl ...
- scrapy爬取boss直聘实习生数据
这个..是我最近想找实习单位..结果发现boss上很多实习单位名字就叫‘实习生’.......太不讲究了 == 难怪一直搜不到..咳,其实是我自己水平有限,有些简历根本就投不出去 == 所以就想爬下b ...
- Pyhton爬虫实战 - 抓取BOSS直聘职位描述 和 数据清洗
Pyhton爬虫实战 - 抓取BOSS直聘职位描述 和 数据清洗 零.致谢 感谢BOSS直聘相对权威的招聘信息,使本人有了这次比较有意思的研究之旅. 由于爬虫持续爬取 www.zhipin.com 网 ...
- scrapy——7 scrapy-redis分布式爬虫,用药助手实战,Boss直聘实战,阿布云代理设置
scrapy——7 什么是scrapy-redis 怎么安装scrapy-redis scrapy-redis常用配置文件 scrapy-redis键名介绍 实战-利用scrapy-redis分布式爬 ...
- python分析BOSS直聘的某个招聘岗位数据
前言 毕业找工作,在职人员换工作,离职人员找工作……不管什么人群,应聘求职,都需要先分析对应的招聘岗位,岗位需求是否和自己匹配,常见的招聘平台有:BOSS直聘.拉钩招聘.智联招聘等,我们通常的方法都是 ...
随机推荐
- 页面中加入地图map
1.首先要有密钥AK ,可以自己注册获取或复制别人的 .搜索百度地图API (http://lbsyun.baidu.com/apiconsole/key) 2.地图示例 <head> & ...
- Python内置装饰器@property
在<Python装饰器(Decorators )>一文中介绍了python装饰器的概念,日常写代码时有一个装饰器很常见,他就是内置的@property. 我们一步步的来接近这个概念. 一个 ...
- 寝室远程连接室友mysql数据库
注意,本方法是适用于同一局域网下的远程连接 注意,本方法是适用于同一局域网下的远程连接 注意,本方法是适用于同一局域网下的远程连接 首先需要修改mysql数据库的相关配置,将user表中的host改为 ...
- C语言 复习函数
什么是函数呢? 首先函数是在完成特定任务的程序代码中,拥有自己独立的单元. 举个例子 “你可以拿本书吗?” ”你可以拿本语文书吗?“ “你可以拿苹果吗?”..... 如果要是放到程序里面估计要重复很多 ...
- Matlab线性规划
线性规划 线性规划的标准形式 \[\underset{x}{min}{\ c^Tx}\ s.t.\ Ax \leqslant b\] 例如,线性规划为: \[ \underset{x}{min ...
- python实现fibonacci数列的三种方法
第一种:递归法 def fibo(n): if n < 3: return 1 return fibo(n-1) + fibo(n-2) print(fibo(6)) 第二种:循环 def fi ...
- python模拟进程状态
python模拟进程状态 我在参考资料中看到了两种实现方式,都做了尝试 代码1 from transitions import Machine class Matter: pass model = M ...
- java之集合工具类Collections
Collections类简介 java.utils.Collections 是集合工具类,用来对集合进行操作.此类完全由在 collection 上进行操作或返回 collection 的静态方法组成 ...
- Python关于去除字符串中空格的方法
Python关于去除字符串中空格的方法 在编写程序时我们经常会遇到需要将字符串中的空格去掉的情况,通常我们可以使用下面几种解决方法: 1.strip()方法:该方法只能把字符串头和尾的空格去掉,但是不 ...
- [译]Vulkan教程(22)创建顶点buffer
[译]Vulkan教程(22)创建顶点buffer Vertex buffer creation 创建顶点buffer Introduction 入门 Buffers in Vulkan are re ...