天眼查有一个高级搜索功能(需要VIP权限,淘宝购买1个7天试用约2元)。
天眼查内的公司大约2.6亿。
高级搜索会限制输出,查询最大输出是10万条。
因此,需要通过限制条件查询的方式,让查询输出小于10万条。
这里采用 区域 + 行业 的条件进行筛选。
获取查询总数
通过浏览器的F12 抓取 勾选条件时,网页触发的数量查询API https://capi.tianyancha.com/cloud-tempest/advance
(天眼查记得打开F12的preserve log,因为它会有基本的反爬技巧,没有打开这个,api很快会被刷掉无法查看)
里面需要注意:headers里必须有一个参数,否则无法查询。(自动解析工具,会漏掉这个的解析)
headers = {"version": "TYC-Web"}
页面解析
页面解析获取需要的公司信息,详见代码。
里面的核心API为
天眼查-商业查询平台_企业信息查询_公司查询_工商查询_企业信用信息系统
需要查看这个API的cookies,headers和data,并用它来发送请求。
优化爬取
先查询区域,如果总数小于上限10万条,则直接按区域爬取,效率最高。
如果超过,则必须加上行业,依次查询(TODO:有个别例如 朝阳和丰台区的某个行业也是超过10万的,需要进一步加筛选条件)。
爬取的每个page size建议为最大值100(每页100个公司)。
爬取过程中,经常会出现网页无效,需要加入重试机制。
测试发现,20并发的查询比较稳定,30并发的爬取网页错误率已经比较明显(加入重试机制,不比20并发快多少)。
解决天眼查的反爬机制
天眼查通过cookie的时间限制,让你从浏览器复制的cookies信息很快失效,无法持续爬取。
cookies中如下3个反爬参数,会定期更新acw_tc是15分钟,acw_sc__v2是1小时,Hm_lpvt_e92c8d65d92d534b0fc290df538b4758是会话周期(你的后面数字可能和我不一样)。
这里通过selenium加载浏览器驱动,每10分钟刷新一次真实页面,并将更新后的cookies信息,更新到爬取代码中,以便于持续爬取。
另外,发送查询的data中,有一个xyz参数,类似密码。如果软件无法爬取成功,需要在浏览器中查看这个值,并更新到代码中。
断点续传
爬取过程中,中断然后继续爬取是一个必须的功能。
这里采用redis记录,(区域+行业作为key,page作为value),程序下次启动会从redis中找到上次的最后page,然后继续爬取。
部分区域行业的page需要反复尝试,才能爬取,因此,程序需要多次运行,才能将尾巴数据爬取干净。
软件相关
线程池还是进程池?
里面用到的lxml的底层是libxml,因此,即使使用的是线程池(python GIL的原因,只能使用1个cpu),在监控也能看到超过100%的CPU使用率。因此放弃资源消耗更高的进程池。
页面解析
页面解析需要将公司名和公司地址定位在一个节点下,因为会存在有些公司没有地址,导致顺序错乱,无法使用的问题。
定位一个节点
xpath('//div[@class="search-item sv-search-company"]')
解析公司名
.find('.//div[@class="info"]')
解析公司地址(这里必须是findall,因为有2个contact row,有一个text有值的,才是地址信息)
.findall('.//div[@class="contact row"]')
写文件
python的open("xxx.txt", "a+")模式,是一个线程安全的追加内容方式,经过大量并发测试,确认无需加锁,可直接使用。