在如今的互联网时代,用户行为数据成为了网站优化和市场分析的宝贵财富。B 站作为国内领先的年轻人文化社区,其用户行为数据对于了解年轻一代的兴趣爱好和行为习惯具有重要意义。本文将详细讲解如何通过 Python 爬虫实现 B 站的模拟登录,并抓取用户行为数据,包括滑动验证码的破解方法。
在开始之前,首先需要搭建好 Python 爬虫环境,确保已安装 Python 解释器,并安装以下必要的库:requests、selenium、pillow、numpy、opencv-python。
# 安装必要的库
!pip install requests selenium pillow numpy opencv-python
打开 B 站的登录页面,通过浏览器开发者工具查看登录过程中的网络请求,分析登录所需的参数和验证流程。
使用 requests 库模拟发送登录请求,需要构造正确的请求头和请求参数,包括用户名、密码等信息。
import requests
def login_bilibili(username, password):
login_url = "https://passport.bilibili.com/api/v3/oauth2/login"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Referer': 'https://www.bilibili.com/'
}
data = {
'username': username,
'password': password
}
response = requests.post(login_url, headers=headers, data=data)
return response.json()
B 站的滑动验证码是一种常见的反爬虫机制,需要通过图像处理和模拟拖动操作来破解。
通过发送请求获取滑动验证码的背景图片和滑块图片。
def get_captcha_images():
# 向验证码图片发送请求
bg_url = "https://passport.bilibili.com/api/v3/oauth2/getKey?appkey=your_appkey"
block_url = "https://passport.bilibili.com/api/v3/oauth2/getKey?appkey=your_appkey&needCaptcha=1"
bg_response = requests.get(bg_url)
block_response = requests.get(block_url)
# 解析返回的 JSON 数据,获取图片 URL
bg_image_url = bg_response.json()['data']['bg']
block_image_url = block_response.json()['data']['block']
# 下载图片
bg_image = requests.get(bg_image_url).content
block_image = requests.get(block_image_url).content
return bg_image, block_image
使用 OpenCV 进行图像处理,计算滑块缺口在背景图片上的位置。
import cv2
import numpy as np
from PIL import Image
def calculate_gap(bg_image, block_image):
# 将图片转换为 OpenCV 格式
bg = cv2.imdecode(np.frombuffer(bg_image, np.uint8), cv2.IMREAD_COLOR)
block = cv2.imdecode(np.frombuffer(block_image, np.uint8), cv2.IMREAD_COLOR)
# 转换为灰度图
bg_gray = cv2.cvtColor(bg, cv2.COLOR_BGR2GRAY)
block_gray = cv2.cvtColor(block, cv2.COLOR_BGR2GRAY)
# 找到滑块缺口的位置
res = cv2.matchTemplate(bg_gray, block_gray, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
return max_loc[0]
使用 Selenium 模拟浏览器进行拖动操作,完成滑动验证码的验证。
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
def simulate_drag(gap):
# 启动浏览器
driver = webdriver.Chrome()
driver.get("https://passport.bilibili.com/login")
# 找到滑块元素
slider = driver.find_element_by_class_name("geetest_slider_button")
# 模拟拖动操作
action = ActionChains(driver)
action.click_and_hold(slider).perform()
action.move_by_offset(gap - 20, 0).perform() # 需要根据实际情况调整偏移量
action.release().perform()
# 等待验证通过
time.sleep(2)
# 关闭浏览器
driver.quit()
通过分析 B 站的用户行为 API,找到获取用户观看记录的接口,然后发送请求获取数据。
def fetch_user_watch_history(headers, user_id):
watch_history_url = f"https://api.bilibili.com/x/web-interface/history/cursor?pn=1&ps=30&vmid={user_id}"
response = requests.get(watch_history_url, headers=headers)
return response.json()
找到对应的 API 接口,发送请求获取用户的点赞和评论数据。
def fetch_user_likes_comments(headers, user_id):
likes_url = f"https://api.bilibili.com/x/web-interface/like?vmid={user_id}"
comments_url = f"https://api.bilibili.com/x/v2/reply/history?pn=1&ps=30&vmid={user_id}"
likes_response = requests.get(likes_url, headers=headers)
comments_response = requests.get(comments_url, headers=headers)
return likes_response.json(), comments_response.json()
将抓取到的 JSON 数据解析为 Python 字典,提取所需信息。
def parse_watch_history(data):
videos = []
for item in data['data']['list']:
video = {
'title': item['title'],
'video_url': item['video_url'],
'play_time': item['play_time'],
'duration': item['duration']
}
videos.append(video)
return videos
def parse_likes_comments(likes_data, comments_data):
likes = []
for item in likes_data['data']:
like = {
'video_title': item['title'],
'video_url': item['url'],
'like_time': item['ctime']
}
likes.append(like)
comments = []
for item in comments_data['data']['list']:
comment = {
'content': item['content'],
'video_title': item['title'],
'comment_time': item['ctime']
}
comments.append(comment)
return likes, comments
将解析后的数据存储到本地文件或数据库中。
import json
def save_data_to_file(data, filename):
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
print(f"数据已保存到 {filename}")
def save_data_to_database(data, connection):
# 根据实际数据库结构进行存储
pass
在上述实战文章中,我们详细讲解了 Python 爬虫模拟登录 B 站及抓取用户行为数据的完整流程,涵盖从环境搭建到数据解析的各个方面,并特别强调了滑动验证码的破解方法。通过这些技术手段,我们能够有效地突破 B 站的反爬机制,获取到宝贵的用户行为数据,为深入分析用户行为提供了坚实的基础。
然而,在实际操作中,我们还需注意以下几点: