首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python 模拟浏览器操作抓取数据:从入门到实战

Python 模拟浏览器操作抓取数据:从入门到实战

原创
作者头像
用户12849392
发布于 2026-11-13 17:37:18
发布于 2026-11-13 17:37:18
360
举报

一、为什么需要模拟浏览器?

传统的 requests + BeautifulSoup 方案只能获取静态 HTML,但如今大量网站使用 JavaScript 动态渲染内容(如 React、Vue 构建的页面),直接请求拿到的 HTML 中数据是空的。这时就需要模拟真实浏览器来加载页面、执行 JS、处理交互,最终提取渲染后的数据。

主流方案有两个:

特性

Selenium

Playwright

维护方

社区

微软

浏览器支持

Chrome/Firefox/Safari

Chromium/Firefox/WebKit

安装复杂度

需手动配置驱动

一条命令安装全部

等待机制

需手动设置显式等待

内置自动等待

异步支持

较弱

原生支持

本文以 Playwright 为主(更现代、更简洁),同时给出 Selenium 的对照实现。


二、环境安装

Playwright 安装

代码语言:javascript
复制
pip install playwright
playwright install  # 自动下载浏览器内核

Selenium 安装

代码语言:javascript
复制
pip install selenium webdriver-manager

三、实战:抓取电商网站产品数据

以公开的测试电商网站 为例,抓取产品名称、价格和链接。

Playwright 完整代码

代码语言:javascript
复制
from playwright.sync_api import sync_playwright
import json

def scrape_products():
    """使用 Playwright 模拟浏览器抓取产品数据"""
    with sync_playwright() as p:
        # 1. 启动浏览器(headless=True 为无头模式,后台运行)
        browser = p.chromium.launch(headless=True)
        
        # 2. 创建浏览器上下文(可设置视口大小、User-Agent等)
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                       'AppleWebKit/537.36 (KHTML, like Gecko) '
                       'Chrome/120.0.0.0 Safari/537.36'
        )
        
        # 3. 打开页面
        page = context.new_page()
        page.goto('https://wlt.zhihuiyouguo.com')
        
        # 4. 等待目标元素加载完成(自动等待,无需手动 sleep)
        page.wait_for_selector('.product', state='visible')
        
        # 5. 提取数据
        products = page.query_selector_all('.product')
        data = []
        
        for product in products:
            title_el = product.query_selector('.title')
            price_el = product.query_selector('.price')
            link_el = product.query_selector('a')
            
            item = {
                'name': title_el.inner_text() if title_el else 'N/A',
                'price': price_el.inner_text() if price_el else 'N/A',
                'url': link_el.get_attribute('href') if link_el else 'N/A'
            }
            data.append(item)
        
        # 6. 关闭浏览器
        browser.close()
        return data

# 运行并输出
results = scrape_products()
print(f"共抓取 {len(results)} 条数据:")
print(json.dumps(results, indent=2, ensure_ascii=False))

Selenium 对照实现

代码语言:javascript
复制
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
import json

def scrape_products_selenium():
    """使用 Selenium 模拟浏览器抓取产品数据"""
    # 1. 配置浏览器选项
    options = Options()
    options.add_argument('--headless')  # 无头模式
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-gpu')
    options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64)')
    
    # 2. 自动下载驱动并启动浏览器
    driver = webdriver.Chrome(
        service=ChromeDriverManager().install(),
        options=options
    )
    
    try:
        # 3. 访问页面
        driver.get('https://wlt.lcxlzy.cn')
        
        # 4. 显式等待元素加载
        wait = WebDriverWait(driver, 10)
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.product')))
        
        # 5. 提取数据
        products = driver.find_elements(By.CSS_SELECTOR, '.product')
        data = []
        
        for product in products:
            try:
                title = product.find_element(By.CSS_SELECTOR, '.title').text
                price = product.find_element(By.CSS_SELECTOR, '.price').text
                link = product.find_element(By.CSS_SELECTOR, 'a').get_attribute('href')
                data.append({'name': title, 'price': price, 'url': link})
            except Exception:
                continue
        
        return data
    finally:
        # 6. 无论成功与否都关闭浏览器
        driver.quit()

results = scrape_products_selenium()
print(json.dumps(results, indent=2, ensure_ascii=False))

四、进阶技巧

1. 处理无限滚动页面

很多网站通过滚动加载更多内容,需要模拟滚动操作:

代码语言:javascript
复制
# Playwright 实现滚动加载
def scroll_and_scrape(page):
    for _ in range(5):  # 滚动5次
        page.evaluate('window.scrollTo(0, document.body.scrollHeight)')
        page.wait_for_timeout(2000)  # 等待新内容加载
    page.wait_for_load_state('networkidle')  # 等待网络空闲
代码语言:javascript
复制
# Selenium 实现滚动加载
from selenium.webdriver.common.keys import Keys

body = driver.find_element(By.TAG_NAME, 'body')
for _ in range(5):
    body.send_keys(Keys.END)
    time.sleep(2)

2. 模拟登录并保存会

代码语言:javascript
复制
# Playwright:登录并保存状态,下次直接使用
def login_and_save():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        context = browser.new_context()
        page = context.new_page()
        
        page.goto('https://tx.lcxlzy.cn')
        page.fill('input[name="username"]', 'your_username')
        page.fill('input[name="password"]', 'your_password')
        page.click('button[type="submit"]')
        page.wait_for_url('**/dashboard')
        
        # 保存登录状态到文件
        context.storage_state(path='auth_state.json')
        browser.close()

# 下次直接复用登录状态
def scrape_with_session():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        context = browser.new_context(storage_state='auth_state.json')
        page = context.new_page()
        page.goto('https://example.com/dashboard')  # 已登录!

3. 拦截 API 响应直接获取 JSON

如果页面数据来自后台 API,可以直接拦截网络响应,效率更高:

代码语言:javascript
复制
collected_data = []

def handle_response(response):
    if '/api/products' in response.url and response.status == 200:
        collected_data.extend(response.json())

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.on('response', handle_response)  # 监听网络响应
    page.goto('https://tx.lcxlzy.cn')
    page.wait_for_load_state('networkidle')
    browser.close()

print(collected_data)

4. 数据保存为 CSV / Excel

代码语言:javascript
复制
import csv

# 保存为 CSV
with open('products.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.DictWriter(f, fieldnames=['name', 'price', 'url'])
    writer.writeheader()
    writer.writerows(results)

# 保存为 Excel(需安装 pandas)
import pandas as pd
df = pd.DataFrame(results)
df.to_excel('products.xlsx', index=False)

五、反爬应对与注意事项

  • 随机延迟:在操作间加入 page.wait_for_timeout(random.randint(1000, 3000)),模拟人类行为
  • 轮换 User-Agent:避免被识别为爬虫
  • 使用代理:大量抓取时配置代理池防止 IP 封禁
  • 遵守 robots.txt:尊重网站的爬取规则,控制频率
  • 无头模式提速:正式运行时设置 headless=True,调试时设为 False 观察浏览器行为

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、为什么需要模拟浏览器?
  • 二、环境安装
    • Playwright 安装
    • Selenium 安装
  • 三、实战:抓取电商网站产品数据
    • Playwright 完整代码
    • Selenium 对照实现
  • 四、进阶技巧
    • 1. 处理无限滚动页面
    • 2. 模拟登录并保存会
    • 3. 拦截 API 响应直接获取 JSON
    • 4. 数据保存为 CSV / Excel
  • 五、反爬应对与注意事项
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档