天天看點

Python爬蟲-使用Selenium模拟百度登入

前言

前面我已經安裝好了Selenium并模拟成功了一下打開百度頁面并進行查詢,讓我這個python初學者信心倍增,今天再來試一試百度登入

正文

把打開百度的代碼放到構造方法中

ps:那個檔案目錄是用于後面滑塊驗證圖檔儲存的。

def __init__(self):

driver = webdriver.Chrome()

driver.get('https://www.baidu.com/')

driver.maximize_window()

self.page = driver

self.filename = 'G:\\scroll\\'

點選右上角的“登入”按鈕,打開登入框,

Python爬蟲-使用Selenium模拟百度登入

代碼如下:

driver = self.page

driver.find_element(By.ID, 's-top-loginbtn').click()

效果是這樣:

Python爬蟲-使用Selenium模拟百度登入

輸入使用者名和密碼,點選登入

driver.find_element(By.ID, 'TANGRAM__PSP_11__userName').send_keys('使用者名')

driver.find_element(By.ID, 'TANGRAM__PSP_11__password').send_keys('密碼')

driver.find_element(By.ID, 'TANGRAM__PSP_11__submit').click()

運作之後,竟然出現了一個滑塊驗證視窗:

Python爬蟲-使用Selenium模拟百度登入

打算用selenium的滑鼠事件,模拟拖拽滑塊的功能

先擷取滑塊的id,發現id竟然是動态變化的,後面有個随機變化的數字

Python爬蟲-使用Selenium模拟百度登入

沒辦法,隻能使用xpath擷取頁面元素

/html/body/div[11]/div[1]/div/div[2]/div[2]

再擷取滑塊要滑動的框的xpath

/html/body/div[11]/div[1]/div/div[2]/div[1]

并擷取這個div元素的寬度,進行移動,代碼如下

flybutton = driver.find_element(By.XPATH, '/html/body/div[11]/div[1]/div/div[2]/div[2]')

ActionChains(driver).move_to_element(flybutton).perform()

flybutton_div = driver.find_element(By.XPATH, '/html/body/div[11]/div[1]/div/div[2]/div[1]')

print(flybutton_div.size['width'], flybutton_div.size['height'])

huakuia = ActionChains(driver)

huakuia.click_and_hold(flybutton).perform()

huakuia.move_by_offset(flybutton_div.size['width'], 0).perform()

huakuia.release()

運作了一下,效果是閃了一下,并沒有滑動

思考良久,并查資料後看到一篇設定滑鼠移動軌迹的文章,遂獲得靈感,可能是移動的太快,被百度反爬工具發現了,于是每次5px循環的移動,

flybutton = driver.find_element(By.XPATH, '/html/body/div[11]/div[1]/div/div[2]/div[2]')

ActionChains(driver).move_to_element(flybutton).perform()

flybutton_div = driver.find_element(By.XPATH, '/html/body/div[11]/div[1]/div/div[2]/div[1]')

print(flybutton_div.size['width'], flybutton_div.size['height'])

huakuia = ActionChains(driver)

huakuia.click_and_hold(flybutton).perform()

x = flybutton_div.size['width']

i = 0

step = 5

while i < x:

i = i + step

huakuia.move_by_offset(step, 0).perform()

time.sleep(3)

huakuia.release()

效果很好,哈哈~,我設定的移動一次休眠3秒,這個可以調快一些,不然心急的可能就認為沒有生效。

Python爬蟲-使用Selenium模拟百度登入

滑動滑塊是生效了,可是依然沒有登入成功,因為系統要求的是把圖檔放正,并不是把滑塊移動最右邊

又進行了大量資料的查詢,搜到一篇文章,是用python實作圖檔方向變換的功能,最關鍵的是裡面實作了計算圖檔傾斜角度的計算,

位址是:python實作圖檔歪斜糾正+代碼和注釋

關鍵代碼如下:

Python爬蟲-使用Selenium模拟百度登入

繼續進行代碼改進

儲存圖檔:

def save_pic(self, file):

pic_url = self.page.find_element(By.XPATH, '/html/body/div[11]/div[1]/div/div[1]/img').get_attribute('src')

headers = {

'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36'

}

res_s = requests.get(pic_url, headers=headers)

data_s = res_s.content

儲存圖檔

with open(file, 'wb') as f:

f.write(data_s)

獲得圖檔傾斜角度

def get_angle(self, file):

# 讀取圖像

img = cv2.imread(file)

# 二值化

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 邊緣檢測

edges = cv2.Canny(gray, 50, 150, apertureSize=3)

# 霍夫變換,摘自https://blog.csdn.net/feilong_csdn/article/details/81586322

lines = cv2.HoughLines(edges, 1, np.pi / 180, 0)

for rho, theta in lines[0]:

a = np.cos(theta)

b = np.sin(theta)

x0 = a * rho

y0 = b * rho

x1 = int(x0 + 1000 * (-b))

y1 = int(y0 + 1000 * (a))

x2 = int(x0 - 1000 * (-b))

y2 = int(y0 - 1000 * (a))

if x1 == x2 or y1 == y2:

return 0

t = float(y2 - y1) / (x2 - x1)

# 得到角度後

rotate_angle = math.degrees(math.atan(t))

改進後的滑塊驗證的代碼如下:

huakuia = ActionChains(driver)

huakuia.click_and_hold(flybutton).perform()

x = flybutton_div.size['width']

i = 0

step = 5

while i < x:

i = i + step

huakuia.move_by_offset(step, 0).perform()

time.sleep(3)

filepath = self.filename + 'scroll' + str(i) + '.png'

print(filepath)

self.save_pic(filepath)

angle = self.get_angle(filepath)

print('current angle is : %s', angle)

if math.fabs(angle) < 3:

break

print('scroll complete')

huakuia.release()

運作之後,還是沒有成功

最後發現計算的圖檔傾斜角度都是一樣的,打開圖檔儲存目錄一看,是下面這樣的:

Python爬蟲-使用Selenium模拟百度登入

原來相同一個圖檔,移動滑塊旋轉後儲存的圖檔都是一樣的,就是初始圖檔的樣子, 怪不得失敗了。。。

繼續查資料,發現selenium有一個截圖的功能,于是使用這個截圖功能去儲存旋轉後的圖檔

img = self.page.find_element(by=By.XPATH, value="/html/body/div[11]/div[1]/div/div[1]")
data_s = img.screenshot(file) # 截取後直接是二進制,無括号           

儲存圖檔後發現還是沒有旋轉前的圖檔,真是心累。。。。。

先記錄在這裡,後面再改進吧