Python自动化爬取天眼查数据的实现
作者:end for time 发布时间:2021-01-10 23:28:27
标签:Python,自动化,爬取
首先要注册一个账号密码,通过账号密码登录,并且滑块验证,自动输入搜索关键词,进行跳转翻页爬取数据,并保存到Excel文件中。
代码运行时,滑块验证经常不通过,被吃掉,但是发现打包成exe运行没有这个问题,100%成功登录。如果大家知道这个问题麻烦请与我分享,谢谢!
废话不多说直接上代码
# coding=utf-8
from selenium import webdriver
import time
from PIL import Image, ImageGrab
from io import BytesIO
from selenium.webdriver.common.action_chains import ActionChains
import os
import sys
import re
import xlwt
import urllib
import datetime
'''
用于天眼查自动登录,解决滑块验证问题
'''
# 获取项目根目录
def app_path():
if hasattr(sys, 'frozen'):
return os.path.dirname(os.path.dirname(os.path.dirname(sys.executable))) #使用pyinstaller打包后的exe目录
return os.path.dirname(__file__)
app_path = app_path()
ready_list = []
#设置表格样式
def set_style(name,height,bold=False):
style = xlwt.XFStyle()
font = xlwt.Font()
font.name = name
# font.bold = bold
font.color_index = 4
font.height = height
style.font = font
return style
# 写excel
f = xlwt.Workbook()
sheet1 = f.add_sheet('企查查数据',cell_overwrite_ok=True)
row0 = ["企业名称","法定代表人","注册资本","成立日期","电话","邮箱","地址"]
for i in range(0, len(row0)):
sheet1.write(0, i, row0[i], set_style('Times New Roman', 220, True))
# 写列
def write_col(data, row, col):
for i in range(0,len(data)):
sheet1.write(row,col,data[i],set_style('Times New Roman',220,True))
row = row + 1
def parse_save_data(all_list):
row = 1
for data in all_list:
# 公司名称
name_list = re.findall(r'<div class="info">(.*?)</div>',data)
print(name_list)
# 标签
tag_list = re.findall(r'<div class="tag-list">(.*)</div><div class="info row text-ellipsis">', data)
tags = []
for list in tag_list:
tag = re.findall(r'<div class="tag-common -primary -new">(.*?)</div>', list)
tags.append(tag)
# print(tags)
# 法定代表人
legal_list = re.findall(r'<a title="(.*?)" class="legalPersonName link-click"',data)
# print(legal_list)
# 注册资本
registered_capital_list = re.findall(r'注册资本:<span title="(.*?)">',data)
# print(registered_capital_list)
# 成立日期
date_list = re.findall(r'成立日期:<span title="(.*?)">',data)
# print(date_list)
# 电话
tel_list = re.findall(r'<div class="triangle" style=""></div><div class=""></div></div></div><span>(.*?)</span>',data)
# print(tel_list)
# 邮箱
email_list = re.findall(r'邮箱:</span><span>(.*?)</span>',data)
# print(email_list)
# 地址
adress_list = re.findall(r'地址:</span><span>(.*?)</span>',data)
# print(adress_list)
write_col(name_list,row,0)
# write_col(tags,1)
write_col(legal_list,row,1)
write_col(registered_capital_list,row,2)
write_col(date_list,row,3)
write_col(tel_list,row,4)
write_col(email_list,row,5)
write_col(adress_list,row,6)
row = row + len(name_list)
s = str([datetime.datetime.now()][-1])
name = '/天眼查数据' + s[:10] + s[-6:] + '.xls'
f.save(app_path + name)
def get_track(distance):
"""
根据偏移量获取移动轨迹
:param distance: 偏移量
:return: 移动轨迹
"""
# 移动轨迹
track = []
# 当前位移
current = 0
# 减速阈值
mid = distance * 2 / 5
# 计算间隔
t = 0.2
# 初速度
v = 1
while current < distance:
if current < mid:
# 加速度为正2
a = 5
else:
# 加速度为负3
a = -2
# 初速度v0
v0 = v
# 当前速度v = v0 + at
v = v0 + a * t
# 移动距离x = v0t + 1/2 * a * t^2
move = v0 * t + 1 / 2 * a * t * t
# 当前位移
current += move
# 加入轨迹
track.append(round(move))
return track
def autologin(account, password):
count = 0
global driver,page,keywords
driver.get('https://www.tianyancha.com/?jsid=SEM-BAIDU-PP-SY-000873&bd_vid=7864822754227867779')
time.sleep(3)
try:
driver.find_element_by_xpath('//*[@id="tyc_banner_close"]').click()
except:
pass
driver.find_element_by_xpath('//div[@class="nav-item -home -p10"]/a').click()
time.sleep(3)
# 这里点击密码登录时用id去xpath定位是不行的,因为这里的id是动态变化的,所以这里换成了class定位
driver.find_element_by_xpath('.//div[@class="sign-in"]/div/div[2]').click()
time.sleep(1)
accxp = './/input[@id="mobile"]'
pasxp = './/input[@id="password"]'
driver.find_element_by_xpath(accxp).send_keys(account)
driver.find_element_by_xpath(pasxp).send_keys(password)
clixp = './/div[@class="sign-in"]/div[2]/div[2]'
driver.find_element_by_xpath(clixp).click()
# 点击登录之后开始截取验证码图片
time.sleep(2)
img = driver.find_element_by_xpath('/html/body/div[10]/div[2]/div[2]/div[1]/div[2]/div[1]')
time.sleep(0.5)
# 获取图片位子和宽高
location = img.location
size = img.size
# 返回左上角和右下角的坐标来截取图片
top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[
'width']
# 截取第一张图片(无缺口的)
screenshot = driver.get_screenshot_as_png()
screenshot = Image.open(BytesIO(screenshot))
captcha1 = screenshot.crop((left, top, right, bottom))
print('--->', captcha1.size)
captcha1.save('captcha1.png')
# 截取第二张图片(有缺口的)
driver.find_element_by_xpath('/html/body/div[10]/div[2]/div[2]/div[2]/div[2]').click()
time.sleep(4)
img1 = driver.find_element_by_xpath('/html/body/div[10]/div[2]/div[2]/div[1]/div[2]/div[1]')
time.sleep(0.5)
location1 = img1.location
size1 = img1.size
top1, bottom1, left1, right1 = location1['y'], location1['y'] + size1['height'], location1['x'], location1['x'] + \
size1['width']
screenshot = driver.get_screenshot_as_png()
screenshot = Image.open(BytesIO(screenshot))
captcha2 = screenshot.crop((left1, top1, right1, bottom1))
captcha2.save('captcha2.png')
# 获取偏移量
left = 55 # 这个是去掉开始的一部分
for i in range(left, captcha1.size[0]):
for j in range(captcha1.size[1]):
# 判断两个像素点是否相同
pixel1 = captcha1.load()[i, j]
pixel2 = captcha2.load()[i, j]
threshold = 60
if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
pixel1[2] - pixel2[2]) < threshold:
pass
else:
left = i
print('缺口位置', left)
# 减去缺口位移
left -= 52
# 开始移动
track = get_track(left)
print('滑动轨迹', track)
# track += [5,4,5,-6, -3,5,-2,-3, 3,6,-5, -2,-2,-4] # 滑过去再滑过来,不然有可能被吃
# 拖动滑块
slider = driver.find_element_by_xpath('/html/body/div[10]/div[2]/div[2]/div[2]/div[2]')
ActionChains(driver).click_and_hold(slider).perform()
for x in track:
ActionChains(driver).move_by_offset(xoffset=x, yoffset=0).perform()
time.sleep(0.2)
ActionChains(driver).release().perform()
time.sleep(1)
try:
if driver.find_element_by_xpath('/html/body/div[10]/div[2]/div[2]/div[2]/div[2]'):
print('能找到滑块,重新试')
# driver.delete_all_cookies()
# driver.refresh()
# autologin(driver, account, password)
else:
print('login success')
except:
print('login success')
time.sleep(0.2)
driver.find_element_by_xpath('.//input[@id="home-main-search"]').send_keys(keywords)
driver.find_element_by_xpath('.//div[@class="input-group home-group"]/div[1]').click()
# 爬数据
data = driver.find_element_by_xpath('.//div[@class="result-list sv-search-container"]').get_attribute('innerHTML')
count = count + 1
# 添加待解析数据
ready_list.append(data)
while count < page:
# 点击下一页
# driver.find_element_by_xpath('./ul[@class="pagination"]]/li/a[@class="num -next"]').click()
url = 'https://www.tianyancha.com/search/p{}?key={}'.format(count + 1,urllib.parse.quote(keywords))
driver.get(url)
time.sleep(2)
data = driver.find_element_by_xpath('.//div[@class="result-list sv-search-container"]').get_attribute('innerHTML')
count = count + 1
ready_list.append(data)
# 解析并写数据
parse_save_data(ready_list)
print('获取数据完毕')
# if __name__ == '__main__':
# driver_path = 'C:/Program Files (x86)/Google/Chrome/Application/chromedriver.exe'
# chromeoption = webdriver.ChromeOptions()
# chromeoption.add_argument('--headless')
# chromeoption.add_argument('user-agent='+user_agent)
keywords = input('请输入关键词:')
account = input('请输入查天眼账号:')
password = input('请输入查天眼密码:')
page = int(input('请输入获取页数:'))
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
print('开始获取数据。。。')
autologin(account, password)
打包成exe(注意site-packages要换成自己python包的目录)
pyinstaller main.py -p D:\Anaconda3\Lib\site-packages
最终运行dist目录下的exe
注意事项
由于天眼查没有开会员只能查看到4页内容,所以需要开会员,这个想要绕过就需要另外去研究,毕竟是要充钱付费,破解也没那么简单
来源:https://blog.csdn.net/qq_36767214/article/details/117843296
0
投稿
猜你喜欢
- MySQL出错代码列表:1005:创建表失败1006:创建数据库失败1007:数据库已存在,创建数据库失败1008:数据库不存在,删除数据库
- 很多人错误地认为ASP是简单、低效的代名词,认为ASP是低能的,不足挂齿的,也很简单,一学就会,一琢磨就精通。有人讲ASP不安全,写ASP的
- 流程,通俗来讲,就是许多人,在做一系列的事情时,怎样相互协调,安排好这一系列事情的先后顺序,有什么事先的约定,需要达到怎样的预期目标。在UE
- 当一个页面上有一百个表单项,你是怎么获取上面的值勤的?这是一段简单的代码,你试试这段代码,试过后,欢迎留言说一下你的想法?index.asp
- js汉字简繁转换源代码:<html> <head> <title>汉字简繁转换工具_asp之家</
- 简介在SQL SERVER中,数据库在硬盘上的存储方式和普通文件在Windows中的存储方式没有什么不同,仅仅是几个文件而已.SQL SER
- 本文实例讲述了PHP抓取及分析网页的方法。分享给大家供大家参考,具体如下:抓取和分析一个文件是非常简单的事。这个教程将通过一个例子带领你一步
- 1、封装的理解封装(Encapsulation):属性和方法的抽象属性的抽象:对类的属性(变量)进行定义、隔离和保护分为私有属性和公开属性:
- 如题,首先读取视频路径,其次根据视频名称创建对应的文件夹,再逐帧将视频帧读入。import cv2import argparseimport
- 在修改后的 《闲谈 Web 图片服务器》 一文中也提及了"IE 浏览器的连接数问题",这也是个有趣的话题。值得补充记录一
- 本文实例讲述了php生成随机数/生成随机字符串的方法。分享给大家供大家参考,具体如下:有时候我们的项目需要生成随机数,但是又不想那么麻烦,那
- 以前我也写过一个注册表类,不过那一个不能进行多个类的注册,下面用数组对类进行了存储。 <?php //基础类 class webSit
- 看一看自己写的类是否能符合这样的标准.要成为高手,我要走的路还很长.摘抄自《OOD 启示录》--Arthur J.Riel(1)所有数据都应
- json_encode()如何转化一个对象? 使用 json_encode() 将数组 array
- 基于很多原因,有不少朋友的空间不支持FSO,当大量的页面生成静态页面时,占用大量的空间,修改样式时,不方便,所以动态页面还是有动态页面的好处
- HTML5之中一个很酷的新特性就是WebSockets,它可以让我们无需AJAX请求即可与服务器端对话。今天彬Go将让大家通过Php环境的服
- 转:coolcode.cn通常情况下,我们的网页要指定一个编码字符集,如 GB2312、UTF-8、ISO-8859-1 
- 多值运动,也就是对于某个对象来说,不仅仅只是其中一个属性值在变化,而是好多个,比如宽,高,字体,透明度等等同时变化当然了,多值运动会产生一个
- 1、前言 MySQL 是完全网络化的跨平台关系型数据库系统,同时是具有客户机/服务器体系结构的分布式数据库管理系统。它具有功能强、使用简便、
- 一:什么是数据库镜像?Robidoux:数据库镜像是将数据库事务处理从一个SQL Server数据库移动到不同SQL Server环境中的另