建立微博cookie池準備 收集微博驗證碼 建立驗證碼資料庫
阿新 • • 發佈:2018-11-05
登入微博weibo.cn會出現驗證碼驗證
可以排列組合算出4*3*2*1=24種,所以可以先用selenium模擬登入擷取這些驗證碼,方便之後獲取cookie時登入驗證,在驗證碼資料庫中匹配,所以寫了這麼一個指令碼獲取驗證碼,其實效率不是很高 ,可以多程序操作,或者用selenium模擬人隨便滑動驗證碼,這時驗證碼會自動更新,不用重新開啟瀏覽器,提升效率。
驗證碼收集全後,手動標記下軌跡。
from io import BytesIO 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 import time from PIL import Image from os import listdir import os from selenium.webdriver.chrome.options import Options class GetCheckPic: def __init__(self, username, password, browser): self.username = username#微博賬號 self.password = password#微博密碼 self.browser = browser#無頭瀏覽器 self.wait = WebDriverWait(self.browser, 20)#等待時間 self.url = "https://passport.weibo.cn/signin/login?entry=mweibo&r=https://m.weibo.cn/"#目標url def open(self):#開啟網頁 self.browser.get(self.url) username = self.wait.until(EC.presence_of_element_located((By.ID, "loginName")))#使用者名稱標籤 password = self.wait.until(EC.presence_of_element_located((By.ID, "loginPassword")))#密碼標籤 submit = self.wait.until(EC.element_to_be_clickable((By.ID, "loginAction")))#提交按鈕標籤 username.send_keys(self.username)#輸入賬號 password.send_keys(self.password)#輸入密碼 time.sleep(1) submit.click()#按提交按鈕 time.sleep(2) def get_position(self):#獲取驗證碼圖片的位置 try: img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, "patt-shadow")))#出現驗證碼圖片的html標籤 except TimeoutError: print("驗證碼未出現") self.open()#未出現驗證碼圖片標籤則重新開啟網頁 time.sleep(2) location = img.location#獲取驗證碼圖片的位置 size = img.size#驗證碼圖片的大小 top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[ 'width']#驗證碼圖片的座標 return top, bottom, left, right def is_pixel_equal(self, image1, image2, x, y):#畫素匹配 threshold = 20#閾值 pixel1 = image1.load()[x, y]#讀取圖片1的畫素 pixel2 = image2.load()[x, y]#讀取圖片2的畫素 RGBA既在原有RGB的的基礎上加上A(透明度) 例如[252,232,255,255] if abs(pixel2[0] - pixel1[0]) < threshold and abs(pixel2[1] - pixel1[1]) < threshold and\ abs(pixel2[2] - pixel1[2]) < threshold:#如果畫素小於閾值則判斷這一個畫素一樣 return True else: return False def get_screenshot(self):#獲得驗證碼的截圖 screenshot = self.browser.get_screenshot_as_png()#截圖用png擷取 screenshot = Image.open(BytesIO(screenshot))#用bytes開啟圖片 return screenshot def get_image(self, n):#獲取驗證碼截圖 top, bottom, left, right = self.get_position() print('驗證碼位置', top, bottom, left, right) screenshot = self.get_screenshot() captcha = screenshot.crop((left, top, right, bottom))#擷取的圖片 print("獲取到驗證碼") if not self.detect_image(captcha):#如果擷取的驗證碼在驗證碼資料庫中沒有則儲存驗證碼 os.chdir(r"D:\untitled\cookie池\login\CheckPic")#驗證碼資料庫 captcha.save(str(n) + ".png") print("儲存成功") os.chdir(r"D:\untitled\cookie池") def same_image(self, image, model):#判斷兩張圖片是否相同 count = 0#如果這個畫素點一樣 則count加1 threshold = 0.99#圖片匹配度的閾值 for x in range(image.width): for y in range(image.height): #匹配每個畫素點 if self.is_pixel_equal(image, model, x, y):#畫素一樣則加一 count += 1 result = float(count)/(image.height * image.width)#匹配度 if result > threshold:#大於匹配度閾值則相同 return True else: return False def detect_image(self, image):#在驗證碼資料庫中檢測 for model in listdir(r"D:\untitled\cookie池\login\CheckPic"):#遍歷驗證碼資料庫中的每張驗證碼 image_path = r"D:\untitled\cookie池\login\CheckPic\\" + model model_image = Image.open(image_path) if self.same_image(image, model_image): print("驗證碼庫中有此驗證碼,重新獲取驗證碼。") return True if __name__ == '__main__': n = 0 while True: n += 1 if len(listdir(r"D:\untitled\cookie池\login\CheckPic")) == 24: break chrome_options = Options() chrome_options.add_argument("--headless") browser = webdriver.Chrome(chrome_options=chrome_options)#無頭模式 get = GetCheckPic("賬號", "密碼", browser) get.open() get.get_position() get.get_image(n) browser.close() print("驗證碼已收集完全。")