需要將模擬的瀏覽器,添加到環境變量中哦。代碼中用的是chrome
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from selenium.common.exceptions import TimeoutException from PIL import Image from io import BytesIO from time import sleep import random """ info: author:CriseLYJ github:https://github.com/CriseLYJ/ update_time:2019-3-7 """ class BiliBili(): """ 登陸B站, 處理驗證碼 電腦的縮放比例需要為100%, 否則驗證碼圖片的獲取會出現問題 """ def __init__( self , username, password): """ 初始化 """ options = webdriver.ChromeOptions() # 設置為開發者模式,避免被識別 options.add_experimental_option( 'excludeSwitches' , [ 'enable-automation' ]) self .browser = webdriver.Chrome(options = options) self .url = 'https://passport.bilibili.com/login' self .browser.get( self .url) self .wait = WebDriverWait( self .browser, 5 , 0.2 ) self .username = username self .password = password def get_button( self ): """ 獲取滑動塊, 并且返回 :return: button """ button = self .wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'gt_slider_knob' ))) return button def get_screenshot( self , button): """ 獲取網頁兩次截圖: 1. 鼠標懸停于button的截圖 2. 鼠標點擊button后的截圖 :param button: 滑動塊 :return: 兩次截圖的結果 """ ActionChains( self .browser).move_to_element(button).perform() screenshot1 = self .browser.get_screenshot_as_png() screenshot1 = Image. open (BytesIO(screenshot1)) ActionChains( self .browser).click_and_hold(button).perform() screenshot2 = self .browser.get_screenshot_as_png() screenshot2 = Image. open (BytesIO(screenshot2)) return (screenshot1, screenshot2) def get_position( self , button): """ 獲取驗證碼圖片的位置 :return: 位置的四個點參數 """ ActionChains( self .browser).move_to_element(button).perform() img = self .wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'gt_box' ))) sleep( 2 ) location = img.location size = img.size print (location, size) top, bottom, left, right = location[ 'y' ], location[ 'y' ] + size[ 'height' ], location[ 'x' ], \ location[ 'x' ] + size[ 'width' ] return top, bottom, left, right def get_geetest_image( self , button, name1 = 'captcha1.png' , name2 = 'captcha2.png' ): """ 獲取兩次驗證碼的截圖: 1. 鼠標懸停于button的截圖 2. 鼠標點擊button后的截圖 :param button: 滑動塊 :param name1: 原始驗證碼保存的名字 :param name2: 缺塊驗證碼保存的名字 :return: 兩次驗證碼截圖的結果 """ top, bottom, left, right = self .get_position(button) print ( '驗證碼位置' , top, bottom, left, right) screenshot = self .get_screenshot(button) captcha1 = screenshot[ 0 ].crop((left, top, right, bottom)) captcha1.save(name1) captcha2 = screenshot[ 1 ].crop((left, top, right, bottom)) captcha2.save(name2) return (captcha1, captcha2) def login( self ): """ 打開瀏覽器,并且輸入賬號密碼 :return: None """ self .browser.get( self .url) username = self .wait.until(EC.element_to_be_clickable((By. ID , 'login-username' ))) password = self .wait.until(EC.element_to_be_clickable((By. ID , 'login-passwd' ))) sleep( 1 ) username.send_keys( self .username) sleep( 1 ) password.send_keys( self .password) def is_pixel_equal( self , img1, img2, x, y): """ 判斷兩個像素是否相同 :param img1: 原始驗證碼 :param img2: 缺塊驗證碼 :param x: 像素點的x坐標 :param y: 像素點的y坐標 :return: 像素是否相同 """ pixel1 = img1.load()[x - 1 , y] pixel2 = img2.load()[x - 1 , y] threshold = 100 if abs (pixel1[ 0 ] - pixel2[ 0 ]) < threshold and abs (pixel1[ 1 ] - pixel2[ 1 ]) < threshold and abs ( pixel1[ 2 ] - pixel2[ 2 ]) < threshold: return True else : return False def get_gap( self , img1, img2): """ 獲取缺口偏移量 :param img1: 原始驗證碼 :param img2: 缺塊驗證碼 :return: 第二個缺塊的左側的x坐標 """ left = 60 # 大致忽略掉第一個缺塊 for i in range (left, img1.size[ 0 ]): for j in range (img1.size[ 1 ]): if not self .is_pixel_equal(img1, img2, i, j): left = i return left return left def get_track( self , distance): """ 獲取滑塊移動軌跡的列表 :param distance: 第二個缺塊的左側的x坐標 :return: 滑塊移動軌跡列表 """ track = [] current = 0 mid = distance * 2 / 3 t = 0.2 v = 0 distance + = 10 # 使滑塊劃過目標地點, 然后回退 while current < distance: if current < mid: a = random.randint( 1 , 3 ) else : a = - random.randint( 3 , 5 ) v0 = v v = v0 + a * t move = v0 * t + 0.5 * a * t * t current + = move track.append( round (move)) for i in range ( 2 ): track.append( - random.randint( 2 , 3 )) for i in range ( 2 ): track.append( - random.randint( 1 , 4 )) print (track) return track def move_button( self , button, track): """ 將滑塊拖動到指定位置 :param button: 滑動塊 :param track: 滑塊運動軌跡列表 :return: None """ ActionChains( self .browser).click_and_hold(button).perform() for i in track: ActionChains( self .browser).move_by_offset(xoffset = i, yoffset = 0 ).perform() sleep( 0.0005 ) sleep( 0.5 ) ActionChains( self .browser).release().perform() def crack( self ): """ 串接整個流程: 1. 輸入賬號密碼 2. 獲取滑動塊 3. 獲取兩張驗證碼圖片 4. 獲取滑塊移動軌跡 5. 將滑塊拖動至指定位置 :return: """ self .login() button = self .get_button() captcha = self .get_geetest_image(button) left = self .get_gap(captcha[ 0 ], captcha[ 1 ]) print (left) track = self .get_track(left) # 如果嘗試登陸失敗, 則重新驗證, 最多三次 times = 0 while times < 3 : self .move_button(button, track) try : success = self .wait.until(EC.text_to_be_present_in_element((By.CLASS_NAME, 'gt_info_type' ), '驗證通過:' )) print (success) except TimeoutException as e: times + = 1 print ( 'fail' ) else : print ( 'success' ) return None if __name__ = = '__main__' : ACCOUNT = input ( '請輸入您的賬號:' ) PASSWORD = input ( '請輸入您的密碼:' ) test = BiliBili(ACCOUNT, PASSWORD) # 輸入賬號和密碼 test.crack() |
以上就是python 模擬登錄B站的示例代碼的詳細內容,更多關于python 模擬登陸B站的資料請關注服務器之家其它相關文章!
原文鏈接:https://github.com/Kr1s77/awesome-python-login-model/blob/master/bilibili/bilibili.py