754 字
4 分钟
基于 Selenium 和 PyQuery 爬取淘宝数据:全自动无头模式实战
1. 爬虫工作原理图
在抓取淘宝这类由 JavaScript 动态渲染的页面时,传统的 requests 库难以获取完整源码。我们使用 Selenium 模拟真实浏览器行为,其核心交互逻辑如下:
2. 环境准备与高级配置
2.1 依赖安装
pip install selenium pyquery2.2 绕过机器人检测(关键)
淘宝会对 window.navigator.webdriver 属性进行检测。如果是 true,系统会立刻弹出滑动验证码。我们必须在启动时通过选项隐藏这个特征。
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC
options = webdriver.ChromeOptions()# 现代无头模式写法options.add_argument('--headless=new')# 禁用沙盒,提升稳定性options.add_argument('--no-sandbox')# 屏蔽 webdriver 特征,防止反爬识别options.add_experimental_option('excludeSwitches', ['enable-automation'])options.add_experimental_option('useAutomationExtension', False)
browser = webdriver.Chrome(options=options)# 执行 CD P命令,修改浏览器内部属性browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", { "source": """ Object.defineProperty(navigator, 'webdriver', { get: () => undefined }) """})wait = WebDriverWait(browser, 10)3. 核心流程解析
3.1 关键词搜索与元素等待
在爬取过程中,网络波动是常态。我们使用 WebDriverWait 配合 Expected Conditions (EC) 来实现“显式等待”,只有当元素真正出现在页面上时才继续。
def search(keyword='美食'): try: browser.get("https://www.taobao.com") # 等待搜索框加载 input_q = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#q'))) # 等待搜索按钮点击 submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'button.btn-search')))
input_q.send_keys(keyword) submit.click()
# 获取总页数 total = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.total'))) get_products() return total.text except Exception as e: print(f"搜索失败: {e}") return search(keyword)3.2 使用 PyQuery 高效解析数据
虽然 Selenium 可以提取文本,但 PyQuery 在解析海量节点时速度更快,且语法类似 jQuery,更加灵活。
from pyquery import PyQuery as pq
def get_products(): # 确保商品列表已加载 wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-itemlist .items .item'))) html = browser.page_source doc = pq(html) items = doc('#mainsrp-itemlist .items .item').items()
for item in items: product = { 'title': item.find('.title').text().strip(), 'price': item.find('.price').text(), 'deal': item.find('.deal-cnt').text(), 'location': item.find('.location').text(), 'shop': item.find('.shop').text(), 'image': item.find('.pic .img').attr('data-src') or item.find('.pic .img').attr('src') } # 建议此处接入 MongoDB 或 CSV 存储 print(f"抓取到: {product['title']}")4. 翻页逻辑与性能建议
翻页时,我们不点击“下一页”按钮,而是直接修改页码框并点击“确定”,这样可以有效防止页码漂移。
def next_page(page_number): try: page_input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'input.input.J_Input'))) submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'span.btn.J_Submit')))
page_input.clear() page_input.send_keys(page_number) submit.click()
# 验证是否成功翻到指定页码 wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, 'li.item.active > span'), str(page_number))) get_products() except TimeoutException: next_page(page_number)5. 进阶反爬策略与总结
爬取淘宝数据的三个重要准则:
- 登录问题:淘宝目前大部分搜索结果都需要登录。建议在启动时加载一个现有的 Chrome User Profile 以保持登录状态,避免频繁弹出的登录框。
- 速度控制:无头模式虽快,但过快的翻页频率会导致 IP 被临时封禁。建议每隔 3-5 页添加一个随机的
time.sleep()。 - 解析后备:如果页面结构变动,优先检查选择器(CSS Selector)。
通过 Selenium + PyQuery 的组合,我们实现了对动态网页的完美兼容。如果你需要处理更复杂的登录验证,下一步可以尝试引入 Cookies 管理 或 代理 IP 池。
基于 Selenium 和 PyQuery 爬取淘宝数据:全自动无头模式实战
https://sw.rscclub.website/posts/python3pachongtbms100/