最近接了个小项目需要批量搜索企查查上的相关企业并把指定信息保存到excel文件中,由于企查查需要登录后才能查看所有搜索到的信息所以第一步需要模拟登录企查查。
python模拟登录企查查最重要的是自动拖拽验证插件
先介绍下项目中使用到的工具与库
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
获取完整项目代码请关注下面的公众号“python客栈”然后回复“qcc”
第一步:下载配置chromedriver
假设电脑中已安装chrome最新版(如果没有安装请自行下载安装),下载与电脑系统、chrome版本相匹配的版本(chromedriver的版本号必须与安装的chrome版本号一至)。
从官网下载的文件是一个压缩包,解压出chromedriver.exe文件,
网上有很多文章说要正常使用chromedriver.exe,需要配置系统的环境变量,其实这是一种比较麻烦的方法。
为了项目的可移动性和操作方便使用另一种方法,就是把chrome浏览器安装目录下的整个application目录都复制到项目目录下,这样就可以随便移动项目到新开发环境中而不用考虑新环境的系统环境变量了。
把解压出chromedriver.exe文件复制到项目目录下的从chrome浏览器安装目录中复制过来的application目录下,保证chromedriver.exe文件与chrome.exe文件在同一目录下。
第二步:安装selenium库
pip安装selenium库
pip install selenium
pycharm开发工具安装selenium库
在pycharm菜单栏中找到并点击【file】->【settings】
在弹出窗口中按下图所示操作
第三步:自动模拟登录企查查python代码编写
首先引入selenium相关库
1
2
3
4
5
6
7
|
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基本配置参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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 }) """ }) |
模拟用户在页面中的一系列操作
1
2
3
4
5
6
7
8
9
10
11
12
|
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值
1
2
3
4
5
6
7
|
driver.execute_cdp_cmd( "page.addscripttoevaluateonnewdocument" , { "source" : """ object.defineproperty(navigator, 'webdriver', { get: () => undefined }) """ }) |
修改完成windows.navigator.webdriver值后再模拟拖动验证插件滑块
1
2
3
4
5
|
# 滑动条定位 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() |
检查验证是否成功
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
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代码
1
2
3
4
|
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访问页面元素写成函数方便以后操作
1
2
3
4
5
|
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头部信息
1
2
3
4
5
6
7
8
9
|
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
1
2
|
cookie = [item[ "name" ] + "=" + item[ "value" ] for item in driver.get_cookies()] headers[ 'cookie' ] = ';' .join(item for item in cookie) |
完整代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
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 |
要获取完整项目代码(selenium模拟登录企查查+requests库自动搜索获取指定信息并保存excel)请关注上面的公众号“python客栈”然后回复“qcc”
本文主要介绍了如何使用python的selenium模拟登录企查查,主要介绍了如何使用selenium保存cookies与headers、自动验证及selenium库对页面元素的一些操作方法
下一篇将介绍python使用requests库自动在企查查上搜索相关企业并获取指定信息