时隔2年多,偶然看到自己的这篇文章,看到下面好多求数据的同学,实在抱歉,一方面之前数据已经丢失,一方面个人博客许久未关注,故没有及时答复。
现在重新发送数据给各位同学,仅作学习使用,需要数据做美赛等数学建模的可以加Q群231436610。
想要完整代码 具体看我的项目 https://gitee.com/yzlit/tianyancha 天眼查爬虫程序,如果你需要更多数据,请帮我在Github点个star就行,可以免费发送行业TOP100企业信息数据和超过3万条的企业数据。
如果不会用git可以在这里下载 代码和数据
注意,上面的项目可以爬取天眼查全部企业数据和 行业TOP100的企业信息,clone下来按wiki指导就能正常运行,由于会定时更新,保证可用。
其他想要商业数据可能要抱歉了,一是数据量肯定达不到你们的要求,另一个本人只是给学习做数据分析的同学使用,。
好,话不多说,直接上代码.
爬取效果如图
先看普通的请求代码,这里应该是爬虫都会用的通用模块,
# -*- coding: utf-8 -*-
import requests
import time
cursor = 0
get_proxy_url = "http://这里是获取代理IP的网址,具体改refresh_proxy_ip()方法实现刷新代理IP"
proxy_id = ""
# 请求url的html内容
def get_html(url):
time.sleep(3)
print(proxy_id)
# 代理 IP ,具体刷新获取代理IP需要自己实现下面的refresh_proxy_ip() 函数
proxy = {
'http': 'http://'+proxy_id,
'https': 'https://'+proxy_id
}
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cache-Control": "max-age=0",
"Connection": "keep-alive",
"Host": "www.tianyancha.com",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
}
try:
# response = requests.get(url, headers=headers, proxies=proxy)
response = requests.get(url,headers=headers, proxies=proxy)
except BaseException:
print("异常发生")
# 这里没有对异常情况作具体处理,只是直接换代理IP 重新请求 就完事昂
refresh_proxy_ip()
return get_html(url)
if response.status_code is not 200:
print("不正常")
refresh_proxy_ip()
return get_html(url)
else:
return response.text
def refresh_proxy_ip():
global proxy_id
time.sleep(1)
proxy_id = requests.get(get_proxy_url).text.replace(" ", "")
print('代理ip请求异常,更换代理IP:http://' + proxy_id + "/")
然后才是对公司url的html内容进行解析,这个没有技巧,一个一个看html结构,有时候天眼查也会反爬做更新,需要及时修改,2020-09-06生效代码如下
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
from mysql import *
from get_html import *
def get_info(url):
html = get_html(url, 1)
soup = BeautifulSoup(html, 'html.parser')
# print(html)
# # 企业logo
# logdiv = soup.find('div', class_="logo -w100")
# imgsrc = ""
# if logdiv is not None:
# img = logdiv.find('img', class_="img")
# if img is not None:
# imgsrc = img.get('data-src')
# # print(html)
# else:
# print("此页查找不到公司log logo -w100:", url)
# 企业简介
div = soup.find('div', id="nav-main-stockNum")
if div is None:
print("此页查找不到公司内容nav-main-stockNum:", url)
# print(html)
# refresh_proxy_ip()
# return get_info(url)
else:
table = div.find('table', class_="table -striped-col")
if table is None:
print("此页查找不到公司内容 table -striped-col:", url)
# refresh_proxy_ip()
# return get_info(url)
else:
tds = table.find_all('td')
if len(tds) <= 31:
print("估计界面有问题:len(tds) <= 31", url)
return True
compCh = tds[1].get_text() # 公司全称
compEn = tds[3].get_text() # 英文名称
sscym = tds[5].get_text() # 上市曾用名
gsdj = tds[7].get_text() # 工商登记
zczb = tds[9].get_text() # 注册资本
sshy = tds[11].get_text() # 所属行业
dsz = tds[13].get_text() # 董事长
dm = tds[15].get_text() # 董秘
fddbr = tds[17].get_text() # 法定代表人
zjl = tds[19].get_text() # 总经理
ygrs = tds[21].get_text() # 员工人数
glryrs = tds[23].get_text() # 管理人员人数
kggd = tds[25].get_text().replace(" ", "") # 控股股东
sjkzr = tds[27].get_text().replace(" ", "") # 实际控制人
zzkzr = tds[29].get_text().replace(" ", "") # 最终控制人
zyyw = tds[31].get_text().replace(" ", "") # 主营业务'
desc = (compCh, compEn, sscym, gsdj, zczb, sshy, dsz, dm, fddbr, zjl, ygrs, glryrs, kggd, sjkzr, zzkzr, zyyw, url)
print(desc)
update_company_qyjj(desc)
# 证券信息
div = soup.find('div', id="nav-main-secBasicInfoCount")
if div is None or len(div) is 0:
print("此页查找不到公司内容nav-main-secBasicInfoCount:", url)
# print(html)
# refresh_proxy_ip()
# return get_info(url)
else:
table = div.find('table', class_="table -striped-col")
if table is None or len(div) is 0:
print("此页查找不到公司内容table -striped-col:", url)
# print(html)
else:
tds2 = table.find_all('td')
if len(tds) <= 13:
print("估计界面有问题:len(tds) <= 13", url)
return True
agdm = tds2[1].get_text() # A股代码
agjc = tds2[3].get_text() # A股简称
bgdm = tds2[5].get_text() # B股代码
bgjc = tds2[7].get_text() # B股简称
hgdm = tds2[9].get_text() # H股代码
hgjc = tds2[11].get_text() # H股简称
zqlb = tds2[13].get_text() # 证券类别
sec_info = (agdm, agjc, bgdm, bgjc, hgdm, hgjc, zqlb, url)
print(sec_info)
update_company_zqxx(sec_info)
# 联系信息
div = soup.find('div', id="_container_corpContactInfo")
if div is None or len(div) is 0:
print("此页查找不到公司内容 _container_corpContactInfo:", url)
# print(html)
# refresh_proxy_ip()
# return get_info(url)
else:
table = div.find('table', class_="table -striped-col -breakall")
if table is None or len(table) is 0:
print("此页查找不到公司内容 table -striped-col -breakall:", url)
# print(html)
# refresh_proxy_ip()
# return get_info(url)
else:
tds = table.find_all('td')
if len(tds) <= 15:
print("估计界面有问题:len(tds) <= 15", url)
return True
lxdh = tds[1].get_text() # 联系电话
dzyx = tds[3].get_text().replace(" ", "") # 电子邮箱
cz = tds[5].get_text() # 传真
gswz = tds[7].get_text() # 公司网址
qy = tds[9].get_text() # 区域
yzbm = tds[11].get_text() # 邮政编码
bgdz = tds[13].get_text().replace(" ", "") # 办公地址
zcdz = tds[15].get_text().replace(" ", "") # 注册地址
contact_info = (lxdh, dzyx, cz, gswz, qy, yzbm, bgdz, zcdz, url)
print(contact_info)
update_company_lxxx(contact_info)
# 公司背景
div = soup.find('div', id="_container_baseInfo")
if div is None:
print("此页查找不到公司内容 _container_baseInfo:", url, "注意这个必须要查到哦哦哦哦哦哦哦!!!!!!!!!!!")
# print(html)
refresh_proxy_ip()
return get_info(url)
else:
compChdiv = soup.find('div', class_="header")
if compChdiv is None:
print("此页查找不到公司全称呼 class_=header:", url, "注意这个必须要查到哦哦哦哦哦哦哦!!!!但先不刷新IP!")
compCh= ""
else:
compCh = compChdiv.find('h1', class_="name").get_text()
print(compCh)
frdiv=div.find('div', class_="humancompany")
if frdiv is None:
print("此页查找不到公司法人 humancompany:", url, "注意这个必须要查到哦哦哦哦哦哦哦!!!!!!!!!!!")
# print(html)
refresh_proxy_ip()
return get_info(url)
table = div.find('table', class_="table -striped-col -border-top-none -breakall")
if table is None:
print("此页查找不到公司内容 table -striped-col -border-top-none -breakall:", url, "注意这个必须要查到哦哦哦哦哦哦哦!!!!!!!!!!!")
# print(html)
refresh_proxy_ip()
return get_info(url)
else:
tds = table.find_all('td')
fddbrr = frdiv.find('a', class_="link-click").get_text() # 法定代表人
if len(tds) <= 40:
print("估计界面有问题:len(tds) <= 40", url)
exit(1)
zczb1 = tds[1].get_text() # 注册资本
sjzb1 = tds[3].get_text() # 实缴资本
clrq1 = tds[6].get_text() # 成立日期
jyzt1 = tds[8].get_text() # 经营状态
tyshxxdm1 = tds[10].get_text() # 统一社会信用代码
gszc1 = tds[12].get_text() # 工商注册号
nsrsbh1 = tds[14].get_text() # 纳税人识别号
zzjgdm1 = tds[16].get_text() # 组织机构代码
gslx1 = tds[18].get_text().replace('\"', "") # 公司类型
hy1 = tds[20].get_text() # 行业
hzrq1 = tds[22].get_text() # 核准日期
djjg1 = tds[24].get_text() # 登记机关
yyqx1 = tds[26].get_text() # 营业期限
nsrzz1 = tds[28].get_text() # 纳税人资质
rygm1 = tds[30].get_text() # 人员规模
cbrs1 = tds[32].get_text() # 参保人数
cym1 = tds[34].get_text() # 曾用名
ywmc1 = tds[36].get_text() # 英文名称
zcdz1 = tds[38].get_text() # 注册地址
jyfw1 = tds[40].get_text() # 经营范围 需要很大的空间 2000
data = (compCh, fddbrr, zczb1, sjzb1, clrq1, jyzt1, tyshxxdm1, gszc1, nsrsbh1, zzjgdm1, gslx1, hy1, hzrq1, djjg1, yyqx1, nsrzz1, rygm1, cbrs1, cym1, ywmc1, zcdz1, jyfw1, True, url)
print(data)
update_company_qybj(data)
return True
代码注释已经打的比较详细,可以直接看。
上面的代码对异常情况的处理并没有太细致,爬取结果还需要数据预处理,尤其是天眼查煞笔的数据加密,
上面加密的数据有,注册资本,注册时间,营业期限,加密方法贼原始,
我遇到的加密是,
数字加密方式
密文 明文
7 4
5 8
4 .
3 9
0 1
. 5
9 2
6 0
1 3
8 6
2 7
就这么简单,哈哈哈,发现这个时没笑死我。这个解码的操作较为简单,小伙伴自己去操练去吧。
有人说,为啥不去爬国家企业信用信息公示系统,原因只有一个,我实在懒得去搞什么滑动验证码,文字点击验证码,看着就烦,(注定无法成为爬虫工程师)需要的伙伴可以看这位老兄的博客,他的说已经失效了,可以借鉴点经验,【爬虫】关于企业信用信息公示系统-加速乐最新反爬虫机制
另外,如果有小伙伴实在不想自己爬数据的,只想要数据的,可以私信或者找我要,这次消息我都会收到,
没错我还真的想过去买点数据应付一下建模,不过看到价格,基本就放弃了
关于如何爬取天眼查90%企业爬虫思路:
就是根据天眼查的条件不断细化,如下细化到行业—》行业子类—》省—》市—》区、县—》分页,基本数据量也5页左右100个公司左右,当然你也可以更细化
如图上条件,已经剩6页,而天眼查不登录请款下只能看5页。
首先是行业,行业有96个:url都是类似:https://www.tianyancha.com/search/oc06 也就是oc+两位数字。
接下来是省:类似吉林省 jl:https://www.tianyancha.com/search/oc06?base=jl
接下来是市:吉林省四平市: https://www.tianyancha.com/search/oc06?base=siping
接下来是区:吉林省四平市铁西区:https://www.tianyancha.com/search/oc06?base=siping&areaCode=220302
接下来是分页:比如第四页p4:https://www.tianyancha.com/search/oc01/p4?base=guangzhou&areaCode=440106
接下来就是每一页的公司url:一般一页有20个公司:https://www.tianyancha.com/company/2782669177
最后就是爬取每一个公司的信息并保存起来了:
把上面每一步爬到先保存到数据库作为准备爬取的页面,即可:
如我上面项目提到的main.py,以下方法你可以用多进程按省1:市区5:分页:25-》公司50来规划分布式机器爬虫。 当然你得够有钱,买得起这么多服务器和代理IP池。
if __name__ == '__main__':
# 一步 一步 爬取所有天眼查所有公司,极其变态
# 把数据库表建好,然后跑这个程序,下面五个可以分五条线程 按先后顺序启动 即可
get_city_to_mysql() # 爬取行业-》省份 url
get_qu_to_mysql() # 爬取行业-》省份-》市 -》区 url
get_page_to_mysql() # 爬取行业-》省份-》市 -》区-》分页 url
get_company_to_mysql() # 爬取行业-》省份-》市 -》区-》分页->公司列表 url
get_company_info_to_mysql() # 爬取公司信息 url