2024实战指南:利用Selenium与Cookie绕过验证,高效爬取QQ空间好友相册
1. 环境准备与基础配置要爬取QQ空间好友相册首先需要搭建Python开发环境。我推荐使用Python 3.8版本这个版本对第三方库的兼容性最好。安装完Python后需要安装几个关键库pip install selenium requests lxml浏览器驱动配置是很多新手容易踩坑的地方。以Chrome为例你需要查看浏览器版本在地址栏输入chrome://version/下载对应版本的ChromeDriver建议放在项目根目录将驱动路径添加到系统环境变量我实测发现浏览器和驱动版本必须完全匹配否则会出现各种奇怪的报错。建议使用Chrome 100版本这个版本对Selenium 4.x的支持最稳定。2. 获取并处理QQ空间Cookie2.1 手动获取Cookie首先用Chrome浏览器登录QQ空间按F12打开开发者工具切换到Network标签页刷新页面找到qzone.qq.com的请求在Headers中找到Cookie信息更简单的方法是安装EditThisCookie插件一键导出所有Cookie。我常用的做法是把Cookie保存为JSON格式{ name: uin, value: o123456789, # 你的QQ号 domain: .qzone.qq.com }2.2 自动加载Cookie通过Selenium加载Cookie时要注意几个关键点from selenium import webdriver from selenium.webdriver.chrome.service import Service service Service(chromedriver.exe) # 驱动路径 driver webdriver.Chrome(serviceservice) driver.get(https://qzone.qq.com) # 必须先访问域名 # 添加Cookie前要先删除可能存在的旧Cookie driver.delete_all_cookies() # 添加Cookie字典 driver.add_cookie({ name: uin, value: 你的QQ号, domain: .qzone.qq.com }) # 必须刷新页面使Cookie生效 driver.refresh()我遇到过Cookie失效的问题后来发现是因为domain设置错误。QQ空间的Cookie作用域要设置为.qzone.qq.com而不是.qq.com。3. 导航到目标好友空间3.1 搜索好友空间登录后需要通过搜索框定位好友空间search_name input(输入好友昵称或备注) driver.find_element(id, friend_search_input).send_keys(search_name) driver.find_element(xpath, //*[idfriends-drop-down]/div[2]/div/div/div[1]/div[1]/button).click()这里有个坑点搜索结果可能不会立即显示需要添加显式等待from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC WebDriverWait(driver, 10).until( EC.presence_of_element_located((xpath, //*[idsearch_friend_result]/li/a)) ).click()3.2 处理新窗口点击好友空间链接后会打开新窗口需要切换窗口句柄# 获取所有窗口句柄 wins driver.window_handles # 切换到最新打开的窗口 driver.switch_to.window(wins[-1])4. 相册数据爬取实战4.1 定位相册入口QQ空间的相册页面通常嵌套在iframe中需要先切换到iframe# 先进入相册tab driver.find_element(xpath, //*[idmenuContainer]/div/ul/li[3]/a).click() # 等待iframe加载 WebDriverWait(driver, 10).until( EC.frame_to_be_available_and_switch_to_it((id, QM_Feeds_Iframe)) )4.2 解析相册列表使用XPath提取相册信息时要注意相对路径的写法from lxml import etree tree etree.HTML(driver.page_source) albums tree.xpath(//ul[idphotoList]/li) for album in albums: title album.xpath(.//h3/a/text())[0] count album.xpath(.//span[classnum]/text())[0] print(f发现相册{title}共{count}张照片)4.3 处理分页加载QQ空间相册采用懒加载需要模拟滚动操作last_height driver.execute_script(return document.body.scrollHeight) while True: driver.execute_script(window.scrollTo(0, document.body.scrollHeight);) time.sleep(2) # 等待加载 new_height driver.execute_script(return document.body.scrollHeight) if new_height last_height: break last_height new_height5. 图片下载与存储5.1 提取高清图片链接通过分析发现缩略图URL和大图URL有规律可循thumb_url https://photo.qq.com/xxx/xxx_150.jpg full_url thumb_url.replace(_150.jpg, .jpg) # 去掉尺寸后缀5.2 批量下载实现使用requests库下载时要注意添加Referer头否则会被拒绝headers { User-Agent: Mozilla/5.0, Referer: https://qzone.qq.com } response requests.get(full_url, headersheaders) with open(f{title}/{index}.jpg, wb) as f: f.write(response.content)5.3 异常处理机制我建议为下载添加重试机制for retry in range(3): try: # 下载代码... break except Exception as e: print(f第{retry1}次下载失败{str(e)}) time.sleep(5)6. 反爬应对策略6.1 请求频率控制实测发现请求间隔小于1秒容易触发验证import random time.sleep(random.uniform(1, 3)) # 随机等待1-3秒6.2 浏览器指纹伪装新版Selenium可以通过以下方式隐藏自动化特征options webdriver.ChromeOptions() options.add_argument(--disable-blink-featuresAutomationControlled) options.add_experimental_option(excludeSwitches, [enable-automation])6.3 Cookie保活技巧我通常会在代码中添加Cookie有效性检查if 未登录 in driver.title: print(Cookie已失效需要重新登录) # 重新获取Cookie的逻辑...7. 项目优化建议7.1 使用代理IP池如果需要大量爬取建议配置代理options.add_argument(f--proxy-serverhttp://{proxy_ip}:{proxy_port})7.2 分布式爬虫架构对于好友数量多的情况可以考虑使用Scrapy-Redis实现分布式将好友列表存入Redis队列多个爬虫节点并行处理7.3 数据去重方案建议使用MD5校验图片内容import hashlib def get_file_md5(content): return hashlib.md5(content).hexdigest() # 存储已下载图片的MD5 downloaded_md5 set()我在实际项目中还遇到过相册权限问题非好友或私密相册需要特殊处理。建议先检查相册可见性if 私密 in driver.page_source: print(该相册不可见跳过) continue