🔍 登录 注册

Python 爬虫实战:从 requests 到 Scrapy 的完整进阶之路

小 小卒子 2026-10-20 python 👁 0 ⏱ 6min

Python 爬虫实战:从 requests 到 Scrapy 的完整进阶之路

爬虫是 Python 最经典的实战领域之一。从单脚本抓取到分布式采集,从静态页面到 JS 渲染,本文梳理一条清晰的进阶路径,并重点讲解数据解析、反爬对抗与工程化落地。

一、地基:requests + 解析三板斧

1.1 基础请求

import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36",
    "Referer": "https://example.com/",
}
resp = requests.get("https://api.example.com/list", headers=headers, timeout=10, params={"page": 1})
resp.raise_for_status()
data = resp.json()

三条底线:必须带合理的 UA、必须设 timeout、必须 raise_for_status() 检查状态码。

1.2 解析三件套

| 工具 | 适用场景 | 特点 | |------|----------|------| | 正则 re | 提取 URL、ID 等结构化片段 | 快但脆弱 | | BeautifulSoup | 静态 HTML 的 CSS 选择器 | 简单直观 | | lxml + XPath | 复杂层级、属性提取 | 性能最好 |

from bs4 import BeautifulSoup

soup = BeautifulSoup(resp.text, "lxml")
for item in soup.select("div.article-list > .item"):
    title = item.select_one("h2 a").get_text(strip=True)
    link = item.select_one("h2 a")["href"]
    date = item.select_one(".date").get_text(strip=True)

二、会话、Cookie 与限速

2.1 Session 复用

session = requests.Session()
session.get("https://example.com/login")          # 建立 Cookie
session.post("https://example.com/api/login", json={"user": "u", "pass": "p"})
# 后续请求自动携带登录态
resp = session.get("https://example.com/private/data")

2.2 礼貌爬取:限速与重试

import time
from requests.adapters import HTTPAdapter

session.mount("https://", HTTPAdapter(max_retries=3))
for url in urls:
    session.get(url)
    time.sleep(1)      # 至少 1 秒间隔,避免给目标服务器造成压力

工程意识:爬虫不是攻击,遵守 robots.txt、设置合理间隔、保留来源标识,是长期稳定采集的前提。

三、JS 渲染页面:两种破解思路

3.1 找接口(优先方案)

多数"动态页面"的数据来自 XHR 接口,用浏览器 DevTools 的 Network 面板定位数据接口,直接请求 JSON:

resp = requests.get("https://example.com/api/articles?page=2&size=20", headers=headers)
for item in resp.json()["data"]["items"]:
    print(item["title"])

3.2 无头浏览器兜底

接口加密、签名复杂时,用 Playwright 渲染真实浏览器:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto("https://example.com/list", wait_until="networkidle")
    # 等待数据渲染完成
    page.wait_for_selector(".article-list .item")
    items = page.query_selector_all(".article-list .item")
    for it in items:
        print(it.query_selector("h2 a").inner_text())
    browser.close()

Playwright 的优势:真实渲染、自动等待、支持点击/滚动等交互触发加载。

四、数据清洗与落库

4.1 清洗常规动作

import re

def clean(text: str) -> str:
    text = re.sub(r"<[^>]+>", "", text)     # 去 HTML 标签
    text = re.sub(r"\s+", " ", text)         # 合并空白
    return text.strip()

4.2 批量入库(参数化 + 事务)

import sqlite3

conn = sqlite3.connect("data.db")
with conn:  # 事务自动提交/回滚
    conn.executemany(
        "INSERT OR IGNORE INTO articles(title, url, content, fetched_at) VALUES (?, ?, ?, ?)",
        [(t, u, c, time.time()) for t, u, c in cleaned],
    )

去重策略:URL 建唯一索引 + INSERT OR IGNORE,幂等采集。

五、反爬对抗的正确姿势

5.1 常见的反爬手段与对策

| 反爬手段 | 对策 | |----------|------| | UA 校验 | 随机 UA 池 | | IP 频率限制 | 代理池轮换 + 合理限速 | | 验证码 | 降低频率、优先找接口;必要时接入打码服务 | | 字体反爬 | 下载字体文件映射字形到字符 | | 参数签名 | 逆向 JS、模拟签名算法 | | 登录墙 | Cookie/Session 维持登录态 |

5.2 对抗的道德与技术边界

  • 只在目标允许的范围内采集,尊重 robots.txt 与 ToS;
  • 控制并发与频率,不造成目标服务不可用;
  • 涉及个人信息时注意合规(匿名化、最小化收集)。

六、Scrapy:工程化框架的进阶

单个脚本到 10 个站点、百万级页面时,Scrapy 的异步调度优势凸显:

import scrapy

class ArticleSpider(scrapy.Spider):
    name = "articles"
    start_urls = ["https://example.com/list/1"]

    def parse(self, response):
        for item in response.css(".article-list .item"):
            yield {
                "title": item.css("h2 a::text").get().strip(),
                "url": item.css("h2 a::attr(href)").get(),
            }
        next_page = response.css(".pagination .next::attr(href)").get()
        if next_page:
            yield response.follow(next_page, self.parse)

运行与输出:

scrapy crawl articles -O articles.jsonl

Scrapy 的核心能力:异步并发抓取、自动去重、Pipeline 落库/导出、中间件支持代理与重试、Item 校验。

七、爬虫工程化的五条经验

  1. 先小后大:先抓 20 条验证解析逻辑,再放开全量;
  2. 可观测:每批任务记录成功/失败数与耗时,失败原因分类统计;
  3. 幂等可重跑:断点续爬(记录游标/最后 ID),失败任务可重试;
  4. 隔离环境:爬虫与业务服务分开部署,异常不互相拖累;
  5. 尊重边界:频率、范围、用途都保持克制,才能长久稳定。

结语

爬虫的进阶路径其实很清晰:requests 入门 → 解析与清洗 → 会话与限速 → 反爬对抗 → Scrapy 工程化。真正拉开差距的不是某个酷炫技巧,而是工程习惯——幂等、可观测、有边界。把采集当作"受控的数据管道"来设计,而不是"临时的取数脚本",你的爬虫体系才能支撑起长期稳定的数据业务。

读完了?给作者一点支持

本文采用 CC BY 4.0 协议转载 · © 小卒子

评论(0)

登录 后参与评论。

  • 还没有评论,来抢沙发。

🔗 相关文章