背景
现在企业工商信息都互联网化了,企查查,天眼查和启信宝就是专门做这个,但是这三位都不是省油的灯,网页相似的一匹马,且保密工作做的比谁都好,要从他们哪里拿点数据做研究还是很困难的,但是他们的数据是开放给第三方合作平台的,比如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爬虫仅为学习交流,如有冒犯,请告知删。