深感抱歉
本來這篇文章應該是在昨天發的,可是電腦出了問題藍屏了。晚上回來重裝了系統,結果還是搞到了現在。
今天想和大家聊聊Python與爬蟲
python之所以能迅速風靡全國,和大街小巷各種的培訓機構脫不開關系。
一會pythonAI未來以來,一會兒4個月培養人工智能與機器學習頂尖人才,更有甚者什么一周成就爬蟲分析師…
我這一把年紀了,膽子小只敢在自己的公眾號里說說。至于出去了,你們該實力互吹、生猛造勢的,我看看就好不說話。
網上經??吹脚老x的文章,什么爬了幾十萬數據,一把擼下來幾千萬評論的,聽起來高大上又牛逼。
但其實爬蟲工程師,你看網上有幾個招聘的?為什么,因為
數據有價!
各大廠做什么網絡解決方案的,怎么解決?不得先把各大運營商數據買回來分析了才去解決嗎?天下哪有白吃的午餐。
爬蟲面臨的問題
-
不再是單純的數據一把抓
多數的網站還是請求來了,一把將所有數據塞進去返回,但現在更多的網站使用數據的異步加載,爬蟲不再像之前那么方便
很多人說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,妥妥被封!
-
反反反爬蟲
咱們正常的叫爬蟲,它不讓我們爬,這叫反爬蟲,然后我們用ip代理池的ip,這叫反反爬蟲。結果你發現,人家早就把可用的代理池先一步封了,這叫反反反爬蟲…
免費代理池中,很多代理是不可用或者需要輸入密碼的。好不容易找到一些能用的列表,拉過來添加上發現早就被封掉了,也許是它提前禁掉,也許是別人用過被封了,但結局就是你千辛萬苦找來的,往往最終還是失敗的。
那么我們該怎么辦
-
設置不同的User-Agent
使用pip install fake-useragent
安裝后獲取多種User-Agent,但其實本地保存上幾十個,完全夠了… -
不要太夯(大力)
適當的減慢你的速度,別人不會覺得是你菜…別覺得一秒爬幾千比一秒爬幾百的人牛逼(快槍手子彈打完的早…不算開車吧?)。 -
購買付費的代理
為什么我跳過了說免費的代理?因為現在搞爬蟲的人太多了,免費的基本早就列入各大網站的黑名單了。
說書今天的內容
爬取全國熱點城市的職業,然后對各大城市的薪資進行比較。
原始數據如下:
先來看看python的薪酬榜:
看一下西安的排位,薪資平均真的好低…
至于你說薪資范圍:什么15-20K?放心90%的人入職都只會給你15K的,那10%的人不是你,不是你。
再來看看ruby的:
看這感覺比Python高很多啊…但其實呢?跟百度人均公司3W+一樣,你拿人均算?光幾個總裁年薪上億的,就拉上去了…
但還是可以看到一點,西安的薪酬還是好低…
代碼
代碼其實沒有太多講的,篇幅最多的內容,估計就是我的User-Agent了…
# -*- coding: utf-8 -*-
# @Author : 王翔
# @JianShu : 清風Python
# @Date : 2019/6/14 22:23
# @Software : PyCharm
# @version :Python 3.6.8
# @File : BossCrawler.py
import
requests
from
bs4
import
BeautifulSoup
import
csv
import
random
import
time
import
argparse
from
pyecharts
.
charts
import
Line
import
pandas
as
pd
class
BossCrawler
:
def
__init__
(
self
,
query
)
:
self
.
query
=
query
self
.
filename
=
'boss_info_%s.csv'
%
self
.
query
self
.
city_code_list
=
self
.
get_city
(
)
self
.
boss_info_list
=
[
]
self
.
csv_header
=
[
"city"
,
"profession"
,
"salary"
,
"company"
]
@
staticmethod
def
getheaders
(
)
:
user_list
=
[
"Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16"
,
"Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14"
,
"Mozilla/5.0 (Windows NT 6.0; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 12.14"
,
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0) Opera 12.14"
,
"Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02"
,
"Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00"
,
"Opera/9.80 (Windows NT 5.1; U; zh-sg) Presto/2.9.181 Version/12.00"
,
"Opera/12.0(Windows NT 5.2;U;en)Presto/22.9.168 Version/12.00"
,
"Opera/12.0(Windows NT 5.1;U;en)Presto/22.9.168 Version/12.00"
,
"Mozilla/5.0 (Windows NT 5.1) Gecko/20100101 Firefox/14.0 Opera/12.0"
,
"Opera/9.80 (Windows NT 6.1; WOW64; U; pt) Presto/2.10.229 Version/11.62"
,
"Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.10.229 Version/11.62"
,
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52"
,
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; de) Presto/2.9.168 Version/11.52"
,
"Opera/9.80 (Windows NT 5.1; U; en) Presto/2.9.168 Version/11.51"
,
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; de) Opera 11.51"
,
"Opera/9.80 (X11; Linux x86_64; U; fr) Presto/2.9.168 Version/11.50"
,
"Opera/9.80 (X11; Linux i686; U; hu) Presto/2.9.168 Version/11.50"
,
"Opera/9.80 (X11; Linux i686; U; ru) Presto/2.8.131 Version/11.11"
,
"Opera/9.80 (X11; Linux i686; U; es-ES) Presto/2.8.131 Version/11.11"
,
"Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/5.0 Opera 11.11"
,
"Opera/9.80 (X11; Linux x86_64; U; bg) Presto/2.8.131 Version/11.10"
,
"Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10"
,
"Opera/9.80 (Windows NT 5.1; U; zh-tw) Presto/2.8.131 Version/11.10"
,
"Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1"
,
"Opera/9.80 (X11; Linux x86_64; U; Ubuntu/10.10 (maverick); pl) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (X11; Linux i686; U; ja) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (X11; Linux i686; U; fr) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (Windows NT 6.1; U; zh-tw) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (Windows NT 6.1; U; sv) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (Windows NT 6.1; U; en-US) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (Windows NT 6.1; U; cs) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (Windows NT 6.0; U; pl) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (Windows NT 5.1; U;) Presto/2.7.62 Version/11.01"
,
"Opera/9.80 (Windows NT 5.1; U; cs) Presto/2.7.62 Version/11.01"
,
"Mozilla/5.0 (Windows NT 6.1; U; nl; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01"
,
"Mozilla/5.0 (Windows NT 6.1; U; de; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6 Opera 11.01"
,
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; de) Opera 11.01"
,
"Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00"
,
"Opera/9.80 (X11; Linux i686; U; it) Presto/2.7.62 Version/11.00"
,
"Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.6.37 Version/11.00"
,
"Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.7.62 Version/11.00"
,
"Opera/9.80 (Windows NT 6.1; U; ko) Presto/2.7.62 Version/11.00"
,
"Opera/9.80 (Windows NT 6.1; U; fi) Presto/2.7.62 Version/11.00"
,
"Opera/9.80 (Windows NT 6.1; U; en-GB) Presto/2.7.62 Version/11.00"
,
"Opera/9.80 (Windows NT 6.1 x64; U; en) Presto/2.7.62 Version/11.00"
,
"Opera/9.80 (Windows NT 6.0; U; en) Presto/2.7.39 Version/11.00"
]
user_agent
=
random
.
choice
(
user_list
)
headers
=
{
'User-Agent'
:
user_agent
}
return
headers
def
get_city
(
self
)
:
headers
=
self
.
getheaders
(
)
r
=
requests
.
get
(
"http://www.zhipin.com/wapi/zpCommon/data/city.json"
,
headers
=
headers
)
data
=
r
.
json
(
)
return
[
city
[
'code'
]
for
city
in
data
[
'zpData'
]
[
'hotCityList'
]
[
1
:
]
]
def
get_response
(
self
,
url
,
params
=
None
)
:
headers
=
self
.
getheaders
(
)
r
=
requests
.
get
(
url
,
headers
=
headers
,
params
=
params
)
r
.
encoding
=
'utf-8'
soup
=
BeautifulSoup
(
r
.
text
,
"lxml"
)
return
soup
def
get_url
(
self
)
:
for
city_code
in
self
.
city_code_list
:
url
=
"https://www.zhipin.com/c%s/"
%
city_code
self
.
per_page_info
(
url
)
time
.
sleep
(
10
)
def
per_page_info
(
self
,
url
)
:
for
page_num
in
range
(
1
,
11
)
:
params
=
{
"query"
:
self
.
query
,
"page"
:
page_num
}
soup
=
self
.
get_response
(
url
,
params
)
lines
=
soup
.
find
(
'div'
,
class_
=
'job-list'
)
.
select
(
'ul > li'
)
if
not
lines
:
# 代表沒有數據了,換下一個城市
return
for
line
in
lines
:
info_primary
=
line
.
find
(
'div'
,
class_
=
"info-primary"
)
city
=
info_primary
.
find
(
'p'
)
.
text
.
split
(
' '
)
[
0
]
job
=
info_primary
.
find
(
'div'
,
class_
=
"job-title"
)
.
text
# 過濾答非所謂的招聘信息
if
self
.
query
.
lower
(
)
not
in
job
.
lower
(
)
:
continue
salary
=
info_primary
.
find
(
'span'
,
class_
=
"red"
)
.
text
.
split
(
'-'
)
[
0
]
.
replace
(
'K'
,
''
)
company
=
line
.
find
(
'div'
,
class_
=
"info-company"
)
.
find
(
'a'
)
.
text
.
lower
(
)
result
=
dict
(
zip
(
self
.
csv_header
,
[
city
,
job
,
salary
,
company
]
)
)
print
(
result
)
self
.
boss_info_list
.
append
(
result
)
def
write_result
(
self
)
:
with
open
(
self
.
filename
,
"w+"
,
encoding
=
'utf-8'
,
newline
=
''
)
as
f
:
f_csv
=
csv
.
DictWriter
(
f
,
self
.
csv_header
)
f_csv
.
writeheader
(
)
f_csv
.
writerows
(
self
.
boss_info_list
)
def
read_csv
(
self
)
:
data
=
pd
.
read_csv
(
self
.
filename
,
sep
=
","
,
header
=
0
)
data
.
groupby
(
'city'
)
.
mean
(
)
[
'salary'
]
.
to_frame
(
'salary'
)
.
reset_index
(
)
.
sort_values
(
'salary'
,
ascending
=
False
)
result
=
data
.
groupby
(
'city'
)
.
apply
(
lambda
x
:
x
.
mean
(
)
)
.
round
(
1
)
[
'salary'
]
.
to_frame
(
'salary'
)
.
reset_index
(
)
.
sort_values
(
'salary'
,
ascending
=
False
)
print
(
result
)
charts_bar
=
(
Line
(
)
.
set_global_opts
(
title_opts
=
{
"text"
:
"全國%s薪酬榜"
%
self
.
query
}
)
.
add_xaxis
(
result
.
city
.
values
.
tolist
(
)
)
.
add_yaxis
(
"salary"
,
result
.
salary
.
values
.
tolist
(
)
)
)
charts_bar
.
render
(
'%s.html'
%
self
.
query
)
if
__name__
==
'__main__'
:
parser
=
argparse
.
ArgumentParser
(
)
parser
.
add_argument
(
"-k"
,
"--keyword"
,
help
=
"請填寫所需查詢的關鍵字"
)
args
=
parser
.
parse_args
(
)
if
not
args
.
keyword
:
print
(
parser
.
print_help
(
)
)
else
:
main
=
BossCrawler
(
args
.
keyword
)
main
.
get_url
(
)
main
.
write_result
(
)
main
.
read_csv
(
)
結尾說兩句
- 關于爬蟲的問題,可能言語有些偏激,覺得那里說的不對的,大家可以在評論區討論。
- 如果大家覺得這種個人言論過多的帖子不適合你們學習,也可以評論或者私信我,我以后少說點。
- ** 這點最重要,如果你們覺得我的文章還看得過去,每天更新還算辛苦,就幫忙把公眾號推薦給你身邊同樣喜歡python的朋友**
- 其實這點對我有些重要,如果你看過覺得有收獲,可以點擊文章右下角的**“在看”**讓我知道。
- 代碼和數據和html,老規矩公眾號回復 boss ,即可獲取文章的數據、代碼及pyecharts生成好的html文件…
今天的內容就到這里,如果覺得有幫助,記得點贊支持。歡迎大家關注我的公眾號
【清風Python】
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
