很多時候時候我們再分析登入請求的時候,發現登入算法非常麻煩,我們很多時候沒有辦法通過前面的Requests來登入,或者需要花費大量的時間,是以我們建議如果比較複雜的登入可以使用Selenium來登入。比如我們下面的案例,登入支付寶,我們分析發現光登入支付寶就傳遞了30多個參數。
注意
Selenium模拟登入性能相對Requests這種方式來說性能比較低,是以建議先分析接口然後再決定是否使用Selenium模拟登入。
一、使用Selenium模拟登入
前一章我們已經介紹了Selenium的安裝與使用,是以我們直接開始使用。
1、導入Selenium
為了友善調試,我們這裡使用Chrome驅動;如果到生産環境,我們可以使用PhantomJS或者使用Chrom/FireFox無頭模式Headless代替PhantomJS,這樣他們的性能相對有所提高!
from selenium import webdriver
driver = webdriver.Chrome()
2、定位元素以及輸入賬号密碼
我們可以使用driver.get加載網頁,這裡我們可以通過show_login切換到密碼登入
driver.get("https://auth.alipay.com/login/index.htm")
driver.find_element_by_xpath("//li[@data-status='show_login']").click()
for usname in self.username:
driver.find_element_by_id("J-input-user").send_keys(usname)
time.sleep(0.2)
for pwd in self.password:
driver.find_element_by_id("password_rsainput").send_keys(pwd)
time.sleep(0.2)
time.sleep(10)
driver.find_element_by_id("J-login-btn").click()
研究發現支付寶會監控輸入速度,如果直接send_keys你會發現無論如何都會登入失敗。
是以我們就緩慢輸入,同時我們可以根據ID定位以及輸入值。
3、擷取登入後的網頁
登入後我們可以頁面會自動跳轉到使用者中心,我們可以使用driver.page_source來擷取登入中心的代碼,我們可以使用BeautifulSoup來解析頁面代碼
html = driver.page_source
soup = BeautifulSoup(html,"lxml")
table = soup.find("table",id="tradeRecordsIndex")
二、完整代碼
我們在一些情況下會應用到time.sleep,為了友善我們可以在測試中調試和處理
# coding=utf-8
import time
from selenium import webdriver
from bs4 import BeautifulSoup
class Alipay:
def __init__(self,username,password):
self.username = username
self.password = password
self.driver = webdriver.Chrome()
def login(self):
driver = self.driver
driver.get("https://auth.alipay.com/login/index.htm")
driver.find_element_by_xpath("//li[@data-status='show_login']").click()
for usname in self.username:
driver.find_element_by_id("J-input-user").send_keys(usname)
time.sleep(0.2)
for pwd in self.password:
driver.find_element_by_id("password_rsainput").send_keys(pwd)
time.sleep(0.2)
time.sleep(10)
driver.find_element_by_id("J-login-btn").click()
records = self.getRecord(driver)
return records
def getRecord(self,driver):
html = driver.page_source
soup = BeautifulSoup(html,"lxml")
table = soup.find("table",id="tradeRecordsIndex")
records = []
if table:
trs = table.find_all("tr")
for tr in trs:
tds = tr.find_all("td")
created_at = tds[1].text
order = tds[2].text
money = tds[3].text
records.append({"time":created_at.replace("\n",""),"order":order.replace("\n",""),"money":money.replace("\n","")})
return records
if __name__ == '__main__':
alipay = Alipay("","")
logins = alipay.login()
print(logins)