背景
現在企業工商信息都互聯網化了,企查查,天眼查和啓信寶就是專門做這個,但是這三位都不是省油的燈,網頁相似的一匹馬,且保密工作做的比誰都好,要從他們哪裏拿點數據做研究還是很困難的,但是他們的數據是開放給第三方合作平臺的,比如58和百度百聘,通過第三方合作平臺獲取企業信息或許會比直接從這三個平臺獲取輕鬆一些,這次選擇百度百聘嘗試。
思路
由於百度百聘時異步加載,這次選擇webdriver模擬爬取,雖然慢了點,但還是根據其每個城市的企業數據量還是可行的,總體思路就是模擬人去瀏覽他們的網頁,一頁一頁點進去獲取相應的字段,話不多說,代碼見。
完整代碼
# -*- coding: utf-8 -*-
"""
project_name:百度百聘模擬抓取
@author: 帥帥de三叔
Created on Mon Dec 30 10:15:49 2019
"""
import time #導入時間管理模塊
import pymysql #導入數據框模塊
import requests #導入網頁請求模塊
from bs4 import BeautifulSoup
from selenium import webdriver #導入模擬驅動
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
header={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
"Accept":"*/*",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Connection": "keep-alive"} #構造請求頭
db=pymysql.connect("localhost","root","123456","baidu_recruit_employ",charset="utf8") #連接數據庫
cursor=db.cursor() #創建遊標
cursor.execute("drop table if exists recruit_employ") #以重寫的方式寫入
c_sql="""create table recruit_employ(
city varchar(10), #城市,總部所在地
title varchar(20), #公司名稱
industry varchar(50), #所屬行業
website varchar(20), #官網
salary varchar(10), #平均薪資
registeredCapital varchar(40),#註冊資本
registration_time varchar(14), #註冊時間
registeration_address varchar(30), #註冊地
stype varchar(20)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8MB4"""
cursor.execute(c_sql) #執行創建表操作
def get_message(city,company_list,page): #定義獲取信息函數
for i in range(1,len(company_list)+1):
url_click="//*[@id='qz-list-box']/div["+str(i)+"]/div[1]" #構造詳情頁點擊xpath
driver.find_element_by_xpath(url_click).click() #進入公司詳情頁
driver.switch_to.window(driver.window_handles[1])#切換當前頁面標籤
time.sleep(1) #進程掛起1秒
print("公司詳情頁爲:",driver.current_url) #公司詳情頁
response=requests.get(driver.current_url,headers=header)
#response.encoding=requests.utils.get_encoding_from_headers(response.headers)
answer=BeautifulSoup(response.text,'lxml')
city=city
try:
title=answer.find("div",class_="title").get_text() #公司名稱
except:
title=""
try:
industry=answer.find("span",class_="select-content ellipsis").get_text() #所屬行業
except:
industry=""
try:
website=answer.findAll("div",class_="line-equal-item border-left")[0].find("span",class_="select-content").get_text() #官網
except:
website=""
try:
salary=answer.findAll("div",class_="line-equal-item border-left")[-2].find("span",class_="select-content").get_text() #平均薪資
except:
salary=""
try:
registeredCapital=driver.find_element_by_xpath("/html/body/div[1]/div/div[3]/div[4]/div[1]/div/div/div[2]/div[2]/p[2]").text.split(":")[-1] #註冊資本
except:
registeredCapital=""
try:
registration_time=driver.find_element_by_xpath("/html/body/div[1]/div/div[3]/div[4]/div[1]/div/div/div[2]/div[2]/p[4]").text.split(":")[-1] #註冊時間
except:
registration_time=""
try:
registeration_address=driver.find_element_by_xpath("/html/body/div[1]/div/div[3]/div[4]/div[1]/div/div/div[2]/div[2]/p[6]").text.split(":")[-1] #註冊地址
except:
registeration_address=""
try:
stype=driver.find_element_by_xpath("/html/body/div[1]/div/div[3]/div[4]/div[1]/div/div/div[2]/div[2]/p[5]").text.split(":")[-1] #企業類型
except:
stype=""
print(city,title,industry,website,salary,registeredCapital,registration_time,registeration_address,stype)
insert_data=("insert into recruit_employ(city,title,industry,website,salary,registeredCapital,registration_time,registeration_address,stype)""values(%s,%s,%s,%s,%s,%s,%s,%s,%s)")
company_data=([city,title,industry,website,salary,registeredCapital,registration_time,registeration_address,stype])
cursor.execute(insert_data,company_data)
db.commit()
driver.close()
driver.switch_to_window(driver.window_handles[0])
driver.find_element_by_xpath("/html/body/div[1]/div/div[4]/div[2]/div[1]/div[3]/span[8]").click() #點擊下一頁
page=page+1
time.sleep(1)
company_list=driver.find_element_by_class_name("listitem").find_elements_by_class_name("title") #企業列表名稱
if __name__=="__main__":
citys=["上海","北京","廣州","深圳","南京","杭州","武漢"]
for city in citys:
url="https://zhaopin.baidu.com/firm?city={}".format(city)
driver=webdriver.Chrome(executable_path="C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe") #驅動初始化options=chrome_options
driver.get(url) #首頁
driver.implicitly_wait(1)#設置隱性等待時間
company_list=driver.find_element_by_class_name("listitem").find_elements_by_class_name("title") #企業列表名稱
page=1
while company_list:
page=page+1
get_message(city,company_list,page)
print("當前頁面:",page)
代碼解析
代碼模擬的過程大致是先進入首頁,然後查看是否有企業列表,如果有一個一個獲取企業詳情頁,點擊進去獲取詳情頁的url, 換用requests請求或者相應字段,對於沒法用requests找到的字段,用webdriver查找元素的辦法找出來,在詳情頁找完對應字段後,然後再返回之前的企業列表頁,把當前頁所有企業列表都循環完,找到下一頁元素點擊進入下一頁,執行同樣操作。當翻頁到最後頁的時候下一頁會報錯,會說企業詳情頁列表找不到,可以嘗試用try except 來消除,意味着所有頁碼都翻完了,程序結束。
代碼中options=chrome_options表示不打開瀏覽器,或許會節省點時間。
一共76頁,一頁10家企業,一共760家企業。並不像首頁說的1萬6千多家企業。
改進思路
由於前面模擬爬取並不算很成功,所以迴歸原始的 requests請求,異步加載就異步加載,先試試再說,開始的時候還有上海的企業信息返回,後來都是北京的那幾個企業信息循環返回,懷疑百度百聘加了反爬蟲機制,等待破解。
# -*- coding: utf-8 -*-
"""
project_name:百度百聘
@author: 帥帥de三叔
Created on Wed Dec 25 14:04:00 2019
"""
import urllib.parse
import requests #導入網頁請求模塊
from bs4 import BeautifulSoup #導入網頁解析模塊
import json #導入json
import time #導入時間模塊
import pymysql #導入數據庫模塊
db=pymysql.connect("localhost","root","123456","baidu_recruit_employ",charset="utf8") #連接數據庫
cursor=db.cursor() #創建遊標
cursor.execute("drop table if exists recruit_employ1") #以重寫的方式寫入
c_sql="""create table recruit_employ1(
city varchar(10), #城市,總部所在地
industry varchar(50), #所屬行業
ori_fullname varchar(50), #企業名稱
stype varchar(30), #企業性質
code varchar(16), #平均薪資
registeredCapital varchar(40),#註冊資本
s_salary varchar(10), #平均薪資
number varchar(30), #註冊號
address varchar(50),
registration_time varchar(14),
register_office varchar(20)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8MB4"""
cursor.execute(c_sql) #執行創建表操作
header={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Content-Type": "application/json;charset=utf-8",
"Connection": "keep-alive"} #構造請求頭
def generate_url(city,page): #定義構造一級網頁函數
page=page*10
url="https://zhaopin.baidu.com/api/firmasync?query=&city={}&qid=51288ea64543cc59&pcmod=1&token=FHK3YTpnXrpyYVllsdpmndmace2YXhoaT6Wmeq5aUWpl&pn={}&rn=10".format(city,page)
#print(url)
response=requests.get(url,headers=header).json() #發出請求並json化處理
time.sleep(1) #進程掛起1秒
#print(response)
company_list=response["data"]["result"]["disp_data"] #企業名錄
if company_list:
for i in range(len(company_list)):
try:
city=company_list[i]['city']
except:
city=""
try:
ori_fullname=company_list[i]['ori_fullname']
except:
ori_fullname=""
try:
code=company_list[i]["business"]["code"]
except:
code=""
try:
registeredCapital=company_list[i]["business"]['registered_capital'].strip().replace(" ","")
except:
registeredCapital=""
try:
s_salary=company_list[i]["s_salary"]
except:
s_salary=""
try:
number=company_list[i]["business"]["number"]
except:
number=""
try:
address=company_list[i]["business"]["address"]
except:
address=""
try:
registration_time=company_list[i]["business"]["registration_time"]
except:
registration_time=""
try:
register_office=company_list[i]["business"]["register_office"]
except:
register_office=""
try:
stype=company_list[i]["business"]["type"]
except:
stype=""
try:
industry=company_list[i]["business"]["industry"]
except:
industry=""
print(city,industry,ori_fullname,stype,code,registeredCapital,s_salary,number,address,registration_time,register_office)
insert_data=("insert into recruit_employ1(city,industry,ori_fullname,stype,code,registeredCapital,s_salary,number,address,registration_time,register_office)""values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)")
company_data=([city,industry,ori_fullname,stype,code,registeredCapital,s_salary,number,address,registration_time,register_office])
cursor.execute(insert_data,company_data)
db.commit()
else:
print("no data return")
if __name__=="__main__":
citys=["上海"]#,"北京","廣州","深圳","南京","杭州","武漢"]
pages=100
for city in citys:
city=urllib.parse.quote(city)
#print(city)
for page in range(0,pages):
generate_url(city,page)
免責聲明
Python爬蟲僅爲學習交流,如有冒犯,請告知刪。