使用selenium解决12306的登录问题
最近接觸了一些selenium模塊的相關(guān)知識(shí),覺得還挺有意思的,于是決定親自嘗試寫一些爬蟲程序來(lái)強(qiáng)化selenium模塊(一定要多嘗試、多動(dòng)手、多總結(jié))。本文主要使用python爬蟲來(lái)模擬登錄鐵路12306官網(wǎng)。這兒得吐槽一句,鐵路12306網(wǎng)站的反爬機(jī)制做的還是比較好。特別是12306的驗(yàn)證碼很是令人很頭疼的事,有時(shí)候自己去驗(yàn)證都不一定能通過(guò)。接下來(lái)就使用selenium模塊解決驗(yàn)證碼。
實(shí)現(xiàn)過(guò)程
首先通過(guò)selenium創(chuàng)建一個(gè)瀏覽器,并通過(guò)向頁(yè)面嵌入js代碼去掉webdriver控件(我前面有講過(guò),不懂的大神們可以去看我寫的文章)如果不嵌入js代碼就會(huì)被webdriver控件檢測(cè)出,不管你怎么滑動(dòng)滑塊都是失敗的。
# 繞過(guò)window.navigator.webdriver控件檢測(cè) option = Options() option.add_experimental_option('excludeSwitches', ['enable-automation']) option.add_argument('--disable-blink-features=AutomationControlled')driver = webdriver.Chrome(options=option) driver.maximize_window()# 切換到賬號(hào)密碼登錄窗口 driver.get('https://kyfw.12306.cn/otn/resources/login.html') time.sleep(3) driver.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click() time.sleep(2)?嵌入js代碼這樣就不會(huì)被12306檢測(cè)到是使用selenium自動(dòng)化登錄了。
我們先解決最難的驗(yàn)證碼。為了實(shí)現(xiàn)自動(dòng)化登錄我們使用超級(jí)鷹打碼平臺(tái)。
- 注冊(cè)并登錄超級(jí)鷹賬號(hào):點(diǎn)擊鏈接進(jìn)行注冊(cè)https://www.chaojiying.com/user/login/;
- 點(diǎn)擊購(gòu)買題分,并進(jìn)行充值;
- 點(diǎn)擊軟件id,創(chuàng)建一個(gè)軟件Id(程序中會(huì)用到);
自動(dòng)去幫我們?nèi)プR(shí)別驗(yàn)證碼。
# 初始化超級(jí)鷹 chaojiying = Chaojiying_Client('超級(jí)鷹賬號(hào)', '超級(jí)鷹密碼', '軟件ID') # 沒(méi)有軟件ID的可以去自己在超級(jí)鷹平臺(tái)生成# 處理驗(yàn)證碼 code_img_element = driver.find_element_by_xpath('//*[@id="J-loginImg"]') # 定位到驗(yàn)證碼的位置 # 用超級(jí)鷹去識(shí)別驗(yàn)證碼 dic = chaojiying.PostPic(code_img_element.screenshot_as_png, 9004) # 定位驗(yàn)證碼并截圖,調(diào)用chaojiying里的PostPic類;9004是驗(yàn)證碼類型 result = dic['pic_str'] # x1,y1|x2,y2;超級(jí)鷹返回回來(lái)的數(shù)據(jù)是json格式的 rs_list = result.split("|") for rs in rs_list:p_temp = rs.split(",")x = int(p_temp[0]) # 拿到的是"x"而不是xy = int(p_temp[1])# 要讓鼠標(biāo)移動(dòng)到某一個(gè)位置,然后進(jìn)行點(diǎn)擊ActionChains(driver).move_to_element_with_offset(code_img_element, x, y).click().perform() # 提交事件;以element為原點(diǎn)移動(dòng)鼠標(biāo)去點(diǎn)擊驗(yàn)證碼?驗(yàn)證碼有可能需要我們點(diǎn)擊多個(gè),所以通過(guò)打碼平臺(tái)會(huì)得到多個(gè)坐標(biāo),就比如這種,需要點(diǎn)擊兩次,通過(guò)超級(jí)鷹就會(huì)得到兩個(gè)坐標(biāo)。如下圖。我們發(fā)現(xiàn)有兩個(gè)坐標(biāo)會(huì)有一個(gè)“|”,有三個(gè)坐標(biāo)就有兩個(gè)“|”,所以我們就把他們split下,讓每個(gè)坐標(biāo)嵌套再一個(gè)列表里。我們得到了驗(yàn)證碼的坐標(biāo),下一步就是去點(diǎn)擊驗(yàn)證碼。但是,這個(gè)坐標(biāo)是相對(duì)于驗(yàn)證碼的圖片的坐標(biāo),我們必須用ActionChains來(lái)移動(dòng)一下動(dòng)作鏈的位置。詳細(xì)的輸出過(guò)程如下圖
?最最后就是比較簡(jiǎn)單的傳輸賬號(hào)密碼登錄了
# 輸入用戶名和密碼 driver.find_element_by_xpath('//*[@id="J-userName"]').send_keys('賬號(hào)') driver.find_element_by_xpath('//*[@id="J-password"]').send_keys('密碼') # 點(diǎn)擊登錄按鈕 driver.find_element_by_xpath('//*[@id="J-login"]').click() time.sleep(4)# 移動(dòng)滑塊 btn = driver.find_element_by_xpath('//*[@id="nc_1_n1z"]') ActionChains(driver).drag_and_drop_by_offset(btn, 300, 0).perform() # 拖拽滑塊向右移動(dòng)300像素?這個(gè)代碼是超級(jí)鷹提供的接口。我封裝成一個(gè)類了。
#!/usr/bin/env python # coding:utf-8import requests from hashlib import md5class Chaojiying_Client(object):def __init__(self, username, password, soft_id):self.username = usernamepassword = password.encode('utf8')self.password = md5(password).hexdigest()self.soft_id = soft_idself.base_params = {'user': self.username,'pass2': self.password,'softid': self.soft_id,}self.headers = {'Connection': 'Keep-Alive','User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',}def PostPic(self, im, codetype):"""im: 圖片字節(jié)codetype: 題目類型 參考 http://www.chaojiying.com/price.html"""params = {'codetype': codetype,}params.update(self.base_params)files = {'userfile': ('ccc.jpg', im)}r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)return r.json()def ReportError(self, im_id):"""im_id:報(bào)錯(cuò)題目的圖片ID"""params = {'id': im_id,}params.update(self.base_params)r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)return r.json()if __name__ == '__main__':chaojiying = Chaojiying_Client('超級(jí)鷹賬號(hào)', '超級(jí)鷹密碼', '96001') #用戶中心>>軟件ID 生成一個(gè)替換 96001im = open('a.jpg', 'rb').read() # 本地圖片文件路徑來(lái)替換 a.jpg 有時(shí)WIN系統(tǒng)須要//print(chaojiying.PostPic(im, 1902)) # 1902 驗(yàn)證碼類型 官方網(wǎng)站>>價(jià)格體系 3.4+版 print 后要加()下面是selenium登錄的代碼
from selenium import webdriver import time from chaojiying import Chaojiying_Client from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.chrome.options import Options# 初始化超級(jí)鷹 chaojiying = Chaojiying_Client('超級(jí)鷹賬號(hào)', '超級(jí)鷹密碼.', '軟件ID')# 繞過(guò)window.navigator.webdriver控件檢測(cè) option = Options() option.add_experimental_option('excludeSwitches', ['enable-automation']) option.add_argument('--disable-blink-features=AutomationControlled')driver = webdriver.Chrome() driver.maximize_window()driver.get('https://kyfw.12306.cn/otn/resources/login.html') time.sleep(3) driver.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click() time.sleep(2) # 處理驗(yàn)證碼 code_img_element = driver.find_element_by_xpath('//*[@id="J-loginImg"]') # 用超級(jí)鷹去識(shí)別驗(yàn)證碼 dic = chaojiying.PostPic(code_img_element.screenshot_as_png, 9004) result = dic['pic_str'] # x1,y1|x2,y2 rs_list = result.split("|") for rs in rs_list:p_temp = rs.split(",")x = int(p_temp[0]) # 拿到的是"x"而不是xy = int(p_temp[1])# 要讓鼠標(biāo)移動(dòng)到某一個(gè)位置,然后進(jìn)行點(diǎn)擊ActionChains(driver).move_to_element_with_offset(code_img_element, x, y).click().perform() # 提交事件# 輸入用戶名和密碼 driver.find_element_by_xpath('//*[@id="J-userName"]').send_keys('12306賬號(hào)') driver.find_element_by_xpath('//*[@id="J-password"]').send_keys('12306密碼') # 點(diǎn)擊登錄按鈕 driver.find_element_by_xpath('//*[@id="J-login"]').click() time.sleep(4)# 移動(dòng)滑塊 btn = driver.find_element_by_xpath('//*[@id="nc_1_n1z"]') ActionChains(driver).drag_and_drop_by_offset(btn, 300, 0).perform()總結(jié)
以上是生活随笔為你收集整理的使用selenium解决12306的登录问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 根据设计稿设置rem大小,element
- 下一篇: 2022年全球市场风电铸件总体规模、主要