Python爬蟲實戰之bilibili

SilenceHL發表於2021-04-04

宣告:以下內容均為我個人的理解,如果發現錯誤或者疑問可以聯絡我共同探討

爬蟲介紹

網站介紹

本次要爬取的網站為bilibili,它是國內知名的視訊彈幕網站,這裡有及時的動漫新番,活躍的ACG氛圍,有創意的Up主。可以在這裡找到許多歡樂。

編寫爬蟲的原因和用途

bilibili已經從原來的小破站變成了現在現象級的多元化的社群網站,本次爬取它的目的是以它作為一個典型,告訴大家遇到各型別驗證碼的一種思路。

其實這類網站有個最簡單的辦法,就是提前登陸手動獲取到cookie,然後根據cookie去請求我們需要爬取的網站。個人目的的爬蟲可以用這類方法,比較省編寫程式碼的時間。但是公司中可能會遇到眾多賬戶的爬蟲需求,一個一個手動登入去獲取cookie就比較麻煩了,這時候使用Selenium自動化去獲取效率就高很多了。

Selenium

簡介

正如他們官方的介紹Selenium automates browsers. That's it!,他是一個自動化的瀏覽器,可以模擬人的操作。

使用教程

推薦通過Selenium中文網學習,非常全面!

驗證碼分析

滑動驗證碼

嗶哩嗶哩從之前的驗證碼是滑動驗證碼,主要思路就是找到缺口確定缺口的座標,然後通過Selenium操作滑動到指定位置就行。類似的還有阿里系的大部分網頁,比如飛豬、淘寶、天貓等,不過阿里系的不是每次都需要驗證,得根據實際情況操作。

這種就是找到最右邊的位置資訊,然後滑動即可

這種需要先找到整個圖片的位置,然後滑動先找到內容的輪廓在進行滑動,都是同一個思路演變的

看圖填答案系列

包括東方財富網上交易、bigquant等等,這類比較簡單。將其下載下來根據驗證碼的情況進行處理然後交給各大雲服務商的ORC服務識別就可以,都有免費試用的額度,根據自己的需求和喜好選擇,也可以多試幾家進行對比。

百度騰訊阿里有道智雲

根據圖片進行操作點選系列

目前多了很多這種驗證碼,這種的難度在於情況變化比較多,不僅限於漢字和數字,還有可能是圖片等等,這時候自己想辦法也能解決,但是策略一改變就比較麻煩,可以藉助各類打碼的平臺,對內容進行識別,然後再根據內容去進行操作

易雲打碼快識別網址斐斐打碼等等

bilibili登陸分析

bilibili的最新的驗證碼屬於第三種,在點選登陸按鈕就會出現一個驗證碼的框,我們需要將這個圖片下載下來給打碼平臺去識別,獲得座標資訊然後再用Selenium進行點選操作

bilibili驗證碼

編寫程式碼

Selenium模擬登陸

import re
import time
import base64
import json
import requests
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
​
​
class Bilibili(object):
 def __init__(self):
 chrome_options = Options()
 # 設定無視窗模式
 # chrome_options.add_argument('--headless')
 self.driver = webdriver.Chrome('./chromedriver', options=chrome_options)def login(self, username, password):
 # 開登陸頁面
 self.driver.get("https://passport.bilibili.com/login")
 # 輸入使用者名稱和密碼
 self.driver.find_element_by_id('login-username').send_keys(username)
 self.driver.find_element_by_id('login-passwd').send_keys(password)
 # 點選登陸按鈕
 self.driver.find_element_by_class_name('btn-login').click()
 # 等待驗證碼出現
 # self.driver.implicitly_wait(10)
 time.sleep(5)
 # 獲取圖片所在屬性
 img_style = self.driver.find_element_by_class_name('geetest_tip_img').get_attribute('style')
 # 通過正規表示式獲得圖片url
 url = re.findall('url\("(.*?)"\)', img_style)[0]
 # 通過requests傳送請求得到圖片
 response = requests.get(url).content
 # 將圖片儲存在本地
 with open('./captcha.png', 'wb') as f:
 f.write(response)
 # 通過打碼平臺進行打碼識別
 result = self.captcha_recognition()
 # 識別成功
 if result != "":
 # 對識別到的座標進行分組處理
 result_list = result.split('|')
 for result in result_list:
 x = result.split(',')[0]
 y = result.split(',')[1]
 # 根據座標執行整個動作鏈
 ActionChains(self.driver).move_to_element_with_offset(img_style, int(x), int(y)).click().perform()
 # 點選確定按鈕
 self.driver.find_element_by_class_name('geetest_commit').click()
 # 獲得登陸後的cookie
 cookie = [item["name"] + "=" + item["value"] for item in self.driver.get_cookies()]
 self.driver.close()
 return cookie
​
 def captcha_recognition(self):
 """驗證碼識別"""
 username = 'username'
 password = 'password'
 with open('./captcha.png', 'rb') as f:
 base64_data = base64.b64encode(f.read())
 b64 = base64_data.decode()
 data = {"username": username, "password": password, "typeid": 27, "image": b64}
 result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
 if result['success']:
 return result["data"]["result"]
 else:
 print(result["message"])
 return ""
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章