1. 程式人生 > >建立微博cookie池準備 收集微博驗證碼 建立驗證碼資料庫

建立微博cookie池準備 收集微博驗證碼 建立驗證碼資料庫

登入微博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("驗證碼已收集完全。")