python爬取企查查企业信息之selenium自动模拟登录企查查


Posted in Python onApril 08, 2021

最近接了个小项目需要批量搜索企查查上的相关企业并把指定信息保存到Excel文件中,由于企查查需要登录后才能查看所有搜索到的信息所以第一步需要模拟登录企查查。

python模拟登录企查查最重要的是自动拖拽验证插件

python爬取企查查企业信息之selenium自动模拟登录企查查

先介绍下项目中使用到的工具与库

Python的selenium库:

Web应用程序测试的工具,Selenium可以模拟用户在浏览器中的操作,就像真实用户使用一样。

官方技术文档:https://www.selenium.dev/selenium/docs/api/py/index.html

Chrome浏览器:

谷歌浏览器,不作过多介绍

Chromedriver:

配合Selenium操作Chrome浏览器的驱动程序,注意在下载Chromedriver时必须与已安装的Chrome浏览器版本号前3位保持一至

官方下载地址:http://chromedriver.storage.googleapis.com/index.html

 

第一步:下载配置Chromedriver

假设电脑中已安装Chrome最新版(如果没有安装请自行下载安装),下载与电脑系统、Chrome版本相匹配的版本(Chromedriver的版本号必须与安装的Chrome版本号一至)。

python爬取企查查企业信息之selenium自动模拟登录企查查

从官网下载的文件是一个压缩包,解压出Chromedriver.exe文件,

网上有很多文章说要正常使用Chromedriver.exe,需要配置系统的环境变量,其实这是一种比较麻烦的方法。

为了项目的可移动性和操作方便使用另一种方法,就是把Chrome浏览器安装目录下的整个Application目录都复制到项目目录下,这样就可以随便移动项目到新开发环境中而不用考虑新环境的系统环境变量了。

python爬取企查查企业信息之selenium自动模拟登录企查查

把解压出Chromedriver.exe文件复制到项目目录下的从Chrome浏览器安装目录中复制过来的Application目录下,保证Chromedriver.exe文件与chrome.exe文件在同一目录下。

python爬取企查查企业信息之selenium自动模拟登录企查查

第二步:安装selenium库

pip安装selenium库

pip install selenium

Pycharm开发工具安装selenium库

在Pycharm菜单栏中找到并点击【file】->【settings】

python爬取企查查企业信息之selenium自动模拟登录企查查

在弹出窗口中按下图所示操作

python爬取企查查企业信息之selenium自动模拟登录企查查

第三步:自动模拟登录企查查python代码编写

首先引入selenium相关库

import time
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

初始化webdriver基本配置参数

options = webdriver.ChromeOptions()
    # options.add_argument('--headless')  # 开启无界面模式
    options.add_argument('--disable-gpu')  # 禁用gpu,解决一些莫名的问题
    options.add_argument('blink-settings=imagesEnabled=false')  # 不加载图片, 提升速度
    options.add_argument('--disable-infobars')  # 禁用浏览器正在被自动化程序控制的提示
    options.add_argument('--start-maximized')
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    d = DesiredCapabilities.CHROME
    d['goog:loggingPrefs'] = {'performance': 'ALL'}# 获取Headers必须参数
    driver = webdriver.Chrome(options=options, executable_path="Application/chromedriver.exe", desired_capabilities=d)
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {#清除验证插件中windows.navigator.webdriver的值
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })

模拟用户在页面中的一系列操作

driver.implicitly_wait(2)#延时
    driver.set_window_size(width=800, height=600)
    driver.get("https://www.QCC.com/")
    driver.find_element_by_xpath('//a[@class="navi-btn"][1]').click()
    locator = (By.ID, "dom_id_two")
    try:
        WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator))
    except:
        driver.close()
    # WebDriverWait(driver,20,0.5).until(lambda driver:driver.find_element_by_xpath('//span[@class="nc_iconfont btn_slide"]'))
    # 找到账号输入框
    driver.find_element_by_xpath('//input[@id="nameVerify"]').send_keys('手机号')

自动拖动验证插件滑块并验证

验证插件会检测浏览器是否为webdriver即使用JS检查windows.navigator.webdriver值

所以需要在页面加载前手动修改windows.navigator.webdriver值

driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })

修改完成windows.navigator.webdriver值后再模拟拖动验证插件滑块

# 滑动条定位
    start = driver.find_element_by_xpath('//span[@class="nc_iconfont btn_slide"]')
    action = ActionChains(driver)
    action.click_and_hold(start)
    action.drag_and_drop_by_offset(start, 308, 0).perform()

检查验证是否成功

time.sleep(2)
    style = 'position:absolute;top:0;left:0;width:100%;z-index:999;font-size:40px;line-height:100px;background:rgba(255,217,0,90%);height:100%;text-align:center;color:#000;'
    driver.execute_script(
        'var htm=document.getElementsByClassName("login-sao-panel")[0];htm.innerHTML+="<div style={style}><b id=tt></b><b id=ts></b></div>"'.format(
            style=style))

    ts = driver.find_element_by_id('ts')
    tt = driver.find_element_by_id('tt')

    try:
        driver.find_element_by_xpath('//div[@class="errloading"][1]')
        set_id_att(driver, 'tt', 'innerHTML', '请手工验证')
    except:
        tr = driver.find_element_by_xpath('//span[@class="nc-lang-cnt"][1]')
        if tr.text != '验证通过':
            set_id_att(driver, 'tt', 'innerHTML', '请手工验证')
            # for i in range(1, 6):
            #    if tr.text == '验证通过':
            #        break
            #    set_id_att(driver, 'ts', 'innerHTML', i)
            #    time.sleep(1)
    try:
        driver.find_element_by_xpath('//a[@class="text-primary vcode-btn get-mobile-code"]').click()
    except:
        pass
    # code=driver.find_element_by_xpath('//input[@id="vcodeNormal"]')
    set_id_att(driver, 'tt', 'innerHTML', '请填入手机验证码')
    # rjs='const callback = arguments[arguments.length - 1];callback({v:document.getElementById("vcodeNormal").value})'
    rjs = 'return document.getElementById("vcodeNormal").value'
    locator = (By.CLASS_NAME, "nav-user")
    but = driver.find_element_by_xpath('//form[@id="user_login_verify"]/button')
    for i in range(1, 1):
        # code = driver.execute_async_script(rjs)
        code = driver.execute_script(rjs)
        if len(code) == 6:
            but.click()
            try:
                #WebDriverWait(driver, 5, 0.5).until(EC.presence_of_element_located(locator))
                break
            except:
                pass
                #return 0
        set_id_att(driver, 'ts', 'innerHTML', i)
        time.sleep(1)

上面的代码中在页面里增加了一些状态显示元素及JS代码

style = 'position:absolute;top:0;left:0;width:100%;z-index:999;font-size:40px;line-height:100px;background:rgba(255,217,0,90%);height:100%;text-align:center;color:#000;'
    driver.execute_script(
        'var htm=document.getElementsByClassName("login-sao-panel")[0];htm.innerHTML+="<div style={style}><b id=tt></b><b id=ts></b></div>"'.format(
            style=style))

把selenium访问页面元素写成函数方便以后操作

def set_id_att(bor, id, att, val):
    bor.execute_script('document.getElementById("{a}").{b}="{c}"'.format(a=id, b=att, c=val))

def set_class_att(bor, classs, id, att, val):
    bor.execute_script('document.getElementsByClassName("{a}")[{d}].{b}="{c}"'.format(a=classs, b=att, c=val, d=id))

登录成功后还需要获取页面的headers、Cookie方便后面的requests库使用

selenium获取页面headers头部信息

def getheader(browser):
    for responseReceived in browser.get_log('performance'):
        try:
            response = json.loads(responseReceived[u'message'])[u'message'][u'params'][u'response']
            if response[u'url'] == browser.current_url:
                return response[u'requestHeaders']
        except:
            pass
    return None

selenium获取页面登录后Cookie

cookie = [item["name"] + "=" + item["value"] for item in driver.get_cookies()]
headers['cookie'] = ';'.join(item for item in cookie)

完整代码如下

import time
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

def getheader(browser):
    for responseReceived in browser.get_log('performance'):
        try:
            response = json.loads(responseReceived[u'message'])[u'message'][u'params'][u'response']
            if response[u'url'] == browser.current_url:
                return response[u'requestHeaders']
        except:
            pass
    return None

def set_id_att(bor, id, att, val):
    bor.execute_script('document.getElementById("{a}").{b}="{c}"'.format(a=id, b=att, c=val))

def set_class_att(bor, classs, id, att, val):
    bor.execute_script('document.getElementsByClassName("{a}")[{d}].{b}="{c}"'.format(a=classs, b=att, c=val, d=id))

def login():
    options = webdriver.ChromeOptions()
    # options.add_argument('--headless')  # 开启无界面模式
    options.add_argument('--disable-gpu')  # 禁用gpu,解决一些莫名的问题
    options.add_argument('blink-settings=imagesEnabled=false')  # 不加载图片, 提升速度
    options.add_argument('--disable-infobars')  # 禁用浏览器正在被自动化程序控制的提示
    options.add_argument('--start-maximized')
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    d = DesiredCapabilities.CHROME
    d['goog:loggingPrefs'] = {'performance': 'ALL'}
    driver = webdriver.Chrome(options=options, executable_path="Application/chromedriver.exe", desired_capabilities=d)
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })
    driver.implicitly_wait(2)
    driver.set_window_size(width=800, height=600)
    driver.get("https://www.QCC.com/",)
    driver.find_element_by_xpath('//a[@class="navi-btn"][1]').click()
    locator = (By.ID, "dom_id_two")
    try:
        WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator))
    except:
        driver.close()
    # WebDriverWait(driver,20,0.5).until(lambda driver:driver.find_element_by_xpath('//span[@class="nc_iconfont btn_slide"]'))
    # 找到账号输入框
    driver.find_element_by_xpath('//input[@id="nameVerify"]').send_keys('19942496979')
    # 滑动条定位
    start = driver.find_element_by_xpath('//span[@class="nc_iconfont btn_slide"]')
    action = ActionChains(driver)
    action.click_and_hold(start)
    action.drag_and_drop_by_offset(start, 308, 0).perform()
    time.sleep(2)
    style = 'position:absolute;top:0;left:0;width:100%;z-index:999;font-size:40px;line-height:100px;background:rgba(255,217,0,90%);height:100%;text-align:center;color:#000;'
    driver.execute_script(
        'var htm=document.getElementsByClassName("login-sao-panel")[0];htm.innerHTML+="<div style={style}><b id=tt></b><b id=ts></b></div>"'.format(
            style=style))

    ts = driver.find_element_by_id('ts')
    tt = driver.find_element_by_id('tt')

    try:
        driver.find_element_by_xpath('//div[@class="errloading"][1]')
        set_id_att(driver, 'tt', 'innerHTML', '请手工验证')
    except:
        tr = driver.find_element_by_xpath('//span[@class="nc-lang-cnt"][1]')
        if tr.text != '验证通过':
            set_id_att(driver, 'tt', 'innerHTML', '请手工验证')
            # for i in range(1, 6):
            #    if tr.text == '验证通过':
            #        break
            #    set_id_att(driver, 'ts', 'innerHTML', i)
            #    time.sleep(1)
    try:
        driver.find_element_by_xpath('//a[@class="text-primary vcode-btn get-mobile-code"]').click()
    except:
        pass
    # code=driver.find_element_by_xpath('//input[@id="vcodeNormal"]')
    set_id_att(driver, 'tt', 'innerHTML', '请填入手机验证码')
    # rjs='const callback = arguments[arguments.length - 1];callback({v:document.getElementById("vcodeNormal").value})'
    rjs = 'return document.getElementById("vcodeNormal").value'
    locator = (By.CLASS_NAME, "nav-user")
    but = driver.find_element_by_xpath('//form[@id="user_login_verify"]/button')
    for i in range(1, 1):
        # code = driver.execute_async_script(rjs)
        code = driver.execute_script(rjs)
        if len(code) == 6:
            but.click()
            try:
                #WebDriverWait(driver, 5, 0.5).until(EC.presence_of_element_located(locator))
                break
            except:
                pass
                #return 0
        set_id_att(driver, 'ts', 'innerHTML', i)
        time.sleep(1)

    headers = getheader(driver)#获取headers
    ip = "202.121.178.244"
    if headers:
        #获取cookie并存入headers中
        cookie = [item["name"] + "=" + item["value"] for item in driver.get_cookies()]
        headers['cookie'] = ';'.join(item for item in cookie)
        del headers[':authority']
        del headers[':method']
        del headers[':path']
        del headers[':scheme']
        headers['X-Forwarded-For'] = ip
        headers['X-Remote-IP'] = ip
        headers['X-Originating-IP'] = ip
        headers['X-Remote-Addr'] = ip
        headers['X-Client-IP'] = ip
    return headers

headers=login()#自动登录并获取登录后的Headers包括cookies

本文主要介绍了如何使用python的selenium模拟登录企查查,主要介绍了如何使用selenium保存Cookies与headers、自动验证及selenium库对页面元素的一些操作方法。

Python 相关文章推荐
python 快速排序代码
Nov 23 Python
Python基于scrapy采集数据时使用代理服务器的方法
Apr 16 Python
基于scrapy实现的简单蜘蛛采集程序
Apr 17 Python
取numpy数组的某几行某几列方法
Apr 03 Python
在python带权重的列表中随机取值的方法
Jan 23 Python
Python基于滑动平均思想实现缺失数据填充的方法
Feb 21 Python
Python3使用Matplotlib 绘制精美的数学函数图形
Apr 11 Python
基于多进程中APScheduler重复运行的解决方法
Jul 22 Python
Python判断字符串是否xx开始或结尾的示例
Aug 08 Python
Python 过滤错误log并导出的实例
Dec 26 Python
python清空命令行方式
Jan 13 Python
浅谈pytorch中torch.max和F.softmax函数的维度解释
Jun 28 Python
Python3 使用pip安装git并获取Yahoo金融数据的操作
Apr 08 #Python
Django 如何实现文件上传下载
Apr 08 #Python
python3 删除所有自定义变量的操作
Apr 08 #Python
pytorch显存一直变大的解决方案
Apr 08 #Python
Python文件的操作示例的详细讲解
Django展示可视化图表的多种方式
python tkinter模块的简单使用
You might like
计数器详细设计
2006/10/09 PHP
phpmyadmin 3.4 空密码登录的实现方法
2010/05/29 PHP
php常用字符串处理函数实例分析
2014/11/22 PHP
PHP实现mysqli批量执行多条语句的方法示例
2017/07/22 PHP
PHP赋值的内部是如何跑的详解
2019/01/13 PHP
分析 JavaScript 中令人困惑的变量赋值
2007/08/13 Javascript
JS面向对象编程之对象使用分析
2010/08/19 Javascript
jQuery向上遍历DOM树之parents(),parent(),closest()之间的区别
2013/12/02 Javascript
javascript对话框使用方法(警告框 javascript确认框 提示框)
2014/01/07 Javascript
使用变量动态设置js的属性名
2014/10/19 Javascript
Javascript学习指南
2014/12/01 Javascript
用JavaScript判断CSS浏览器类型前缀的两种方法
2015/10/08 Javascript
JS代码实现table数据分页效果
2016/05/26 Javascript
jQuery使用ajax方法解析返回的json数据功能示例
2017/01/10 Javascript
vue分类筛选filter方法简单实例
2017/03/30 Javascript
React Native自定义控件底部抽屉菜单的示例
2018/02/08 Javascript
JS实现旋转木马轮播图
2020/01/01 Javascript
用python写asp详细讲解
2013/12/16 Python
Python3基础之基本运算符概述
2014/08/13 Python
python 定时修改数据库的示例代码
2018/04/08 Python
python3+PyQt5图形项的自定义和交互 python3实现page Designer应用程序
2020/07/20 Python
Python生成一个迭代器的实操方法
2019/06/18 Python
python实现简单聊天室功能 可以私聊
2019/07/12 Python
python爬虫神器Pyppeteer入门及使用
2019/07/13 Python
tensorflow 实现自定义梯度反向传播代码
2020/02/10 Python
如何使用Django Admin管理后台导入CSV
2020/11/06 Python
webapp字号大小跟随系统字号大小缩放的示例代码
2018/12/26 HTML / CSS
美国餐厅用品和厨房设备批发网站:KaTom Restaurant Supply
2018/01/27 全球购物
数字漫画:comiXology
2020/06/13 全球购物
旅游管理专业学生求职信
2013/09/28 职场文书
2014幼儿园大班工作总结
2014/11/10 职场文书
机关单位2016年创先争优活动总结
2016/04/05 职场文书
护理自荐信
2019/05/14 职场文书
详解OpenCV曝光融合
2022/04/29 Python
Vue操作Storage本地化存储
2022/04/29 Vue.js
zabbix配置nginx监控的实现
2022/05/25 Servers