在「爬蟲的攻守之道(一)」中你可能已經瞭解到了無頭瀏覽器的做用以及使用的方法,那麼本篇文章就讓咱們一塊兒用無頭瀏覽器作點事情。是的你沒有看錯,咱們要「搞」的對象就是百度指數這個網站,不知道你平時是否會應用到這裏面的數據呢?
今天的主要目標就是使用無頭瀏覽器登陸百度指數網站,而且繞開它的人機驗證,不知道你發現沒有,當咱們人爲正常登陸這個網站的時候就不會出現字母、數字或者漢字驗證碼,而使用無頭瀏覽器登陸的時候就會出現這些驗證碼,閒言少敘咱們直接開始正題。前端
一 正常人爲登陸爲何不出現驗證碼?python
咱們在使用瀏覽器正常登陸百度指數網站的時候發現通常不會彈出驗證碼的提示。可是若是你使用無頭瀏覽器去登陸的時候就會出現驗證碼,那麼這二者登陸的區別在哪裏呢?web
通過我不斷的驗證發現了兩個問題,當咱們使用無頭瀏覽器登陸的時候作一些相似於人類的操做,例如在窗口中滑動鼠標,或者改變窗口的大小,這樣百度指數網站就會認爲你是人爲的在操做。chrome
第二個問題就是在咱們使用無頭瀏覽器輸入帳號和密碼的時候,咱們在手動輸入密碼的時候或多或少的在輸入字符之間都會存在時間間隔,而使用無頭瀏覽器的時候程序會零間隔的輸入,這樣百度指數網站就會認爲你是一個程序在輸入了。瀏覽器
二 python無頭瀏覽器準備微信
session
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
import sys
複製代碼word = sys.argv[1] phone = '此處是你登陸百度指數網站的用戶名' password = '此處是你登陸百度指數網站的密碼' 複製代碼
在上面的代碼中咱們引入了一些python的庫,接下來就是使用無頭瀏覽器前的準備工做。app
#打開chrome無頭瀏覽器
opt = webdriver.ChromeOptions()
opt.set_headless()
driver = webdriver.Chrome(options=opt)
executor_url = driver.command_executor._url
session_id = driver.session_id
#將打開的瀏覽區url和session_id存儲起來,提供給下一次應用 file = open('browserMsg.txt','w') file.writelines([executor_url, 'n',session_id]) file.close()less
複製代碼driver.implicitly_wait(20) driver.set_window_size(1000, 800) driver.get("index.baidu.com/v2/main/ind…"+ word +"?words="+ word) 複製代碼
在上面的代碼中咱們使用webdriver的內置函數初始化了無頭瀏覽器,你可能發現我使用了executor_url和session_id變量存儲了點東西,沒錯,我將這次打開的瀏覽器信息(url和sessionId)存儲在了一個txt文件中,這樣下次我再使用百度指數的時候只須要使用python鏈接上這個被存儲信息的無頭瀏覽器進程,那麼就能夠節省掉重複登陸所帶來的風險了,而且還能節省進程數目(此處若是你不須要的話,無需關注)。
接下來咱們隱式等待了20秒,而且將無頭瀏覽器的窗口設置爲了寬1000高800(你能夠改變數值),最後咱們打開了百度指數的網站,而且連接中帶有咱們想要查詢的詞。
三 進軍
time.sleep(1)
driver.set_window_size(1200, 800)
time.sleep(1)
driver.set_window_size(1000, 800)
time.sleep(2)
複製代碼
上面代碼的做用是先將無頭瀏覽器窗口的寬變爲1200,而後再變爲1000,爲了使得此處的操做更像人爲操做,我加了一些延時效果,接下來就是輸入密碼的環節了。
getUserPhoneDom = driver.find_element_by_id('TANGRAM__PSP_4__userName')
getUserPassDom = driver.find_element_by_id('TANGRAM__PSP_4__password')
複製代碼for i in phone: getUserPhoneDom.send_keys(i) time.sleep(.4) for j in password: getUserPassDom.send_keys(j) time.sleep(.4) 複製代碼
在上面的代碼中我先使用了getUserPhoneDom 變量存儲了須要輸入用戶名的輸入框信息,使用getUserPassDom 變量存儲了須要輸入密碼的輸入框信息,而後使用for循環讀取咱們在上面定義的phone和password變量的字符信息,而且每一個字符輸入間隔了400毫秒,這樣作百度指數就認爲你是人爲的在輸入了。
time.sleep(1)
action=ActionChains(driver)
loginDom = driver.find_element_by_id('TANGRAM__PSP_4__submit')
action.move_to_element(loginDom).click().perform()
複製代碼
當咱們輸入完成用戶名和密碼之後咱們只須要找到登陸按鈕的DOM而後進行點擊事件就OK了,到這裏你就能夠成功的繞開百度指數的人機驗證了。
四 總結
繞開某一個網站的人機驗證,重點在於讓機器覺着你是人,而不是它的同類,可是機器覺着你是否是機器的重點在於設計這個機器的人所設置的一些檢驗手段。
對於百度指數來講它的主要檢驗手段在於你打開瀏覽器時的操做,以及輸入用戶名和密碼時的操做,我寫這篇文章的時間是2018年11月18日,在這個節點以前呢,我使用上面的方式繞開百度指數的人機驗證沒有問題,之後有沒有問題,或者說有了問題如何解決仍是要開發你的大腦了。
本文的最後我附上我所有的代碼你能夠複製下來,而且安裝好對應的python包,以及無頭瀏覽器的環境體驗一下。
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
import sys
word = sys.argv[1] phone = '18846927659' password = 'chitianshi...'
#登陸百度指數網站 def login(word, phone, password):
#打開chrome無頭瀏覽器 opt = webdriver.ChromeOptions() opt.set_headless() driver = webdriver.Chrome(options=opt) executor_url = driver.command_executor._url session_id = driver.session_id
#將打開的瀏覽區url和session_id存儲起來,提供給下一次應用 file = open('browserMsg.txt','w') file.writelines([executor_url, 'n',session_id]) file.close()
driver.implicitly_wait(20) driver.set_window_size(1000, 800) driver.get("index.baidu.com/v2/main/ind…"+ word +"?words="+ word)
#當你打開無頭瀏覽器時,你須要操做一下瀏覽器,能夠移動瀏覽器位置,放大或縮小瀏覽器,不然網站會斷定你是爬蟲 #在此,我先等待了1秒,而後放大瀏覽器,而後縮小瀏覽器,而後等待2秒 time.sleep(1) driver.set_window_size(1200, 800) time.sleep(1) driver.set_window_size(1000, 800) time.sleep(2)
#等待2秒之後輸入用戶名和密碼 #先獲取用戶名和密碼的輸入框 getUserPhoneDom = driver.find_element_by_id('TANGRAM__PSP_4__userName') getUserPassDom = driver.find_element_by_id('TANGRAM__PSP_4__password')
#輸入用戶名和密碼的時候不可以一下將用戶名所有輸入,不然網站會斷定你是爬蟲,就會讓你輸入短信驗證碼 #此處我按照字符輸入,而且每一個字符輸入時,間隔400毫秒 for i in phone: getUserPhoneDom.send_keys(i) time.sleep(.4) #密碼的輸入同用戶名的輸入是一個道理 for j in password: getUserPassDom.send_keys(j) time.sleep(.4)
#輸入完用戶名和密碼之後間隔1秒再點擊登陸按鈕 time.sleep(1) #點擊登陸按鈕 action=ActionChains(driver) loginDom = driver.find_element_by_id('TANGRAM__PSP_4__submit') action.move_to_element(loginDom).click().perform()
#網站在登陸的時候會偶爾出現驗證碼,此處是爲了判斷是否出現驗證碼,若是出現就從新執行函數 time.sleep(2) try: errorData = driver.find_element_by_id('TANGRAM__PSP_4__error').text if errorData == "請您輸入驗證碼": login(word, phone, password) except: pass
複製代碼login(word, phone, password) #此處是爲了讓打開的瀏覽器進行一直運行不關閉,以便於後面使用 root = Tk() root.withdraw() root.mainloop() 複製代碼