—— 爬虫项目知识点培训 · 网络爬虫全解 ——

蜘蛛的修炼手册

小哲的公司要做竞品分析和舆情监测——但数据在别人的网站上。手动复制粘贴?3000 个页面会把人逼疯。周师傅说:学爬虫,但先学「规矩」——什么能爬、什么不能爬、怎么爬得又快又稳又不违法。这一本,从 HTTP 到分布式,把爬虫项目的知识点完整走一遍。

🕸️ 🌐 📥 🧩 🖥️ ⚡ 🗄️ 🛡️ ⚖️ 🚀
⚠️ 本手册仅供技术学习与合规使用;爬取数据须遵守 Robots 协议、网站条款与法律法规,尊重他人权益,禁止用于商业侵权。
序 章

数据在金矿里

爬虫 = 用程序替代「手动复制粘贴」
🧑‍💻
小哲

师傅!数据分析要竞品价格、行业新闻、用户评论——3000 个页面,我们组三个人手动复制粘贴了一周才弄了 200 条。老板问「能不能让程序自动抓」?

🧙
周师傅

能——这就是爬虫(Web Crawler / Spider):写程序自动访问网页、提取数据。但开讲之前,先把规矩立了:

  • ✅ 可以爬:公开数据、授权数据、自己网站的数据、学术研究(遵守规则)
  • ⚠️ 慎爬:Robots 协议禁止的、需要登录的、个人隐私数据
  • 🚫 严禁:突破登录/验证码防线、爬取个人信息用于非法用途、大规模抓取影响对方服务

一句话:爬虫技术本身是中性工具,怎么用决定它是「工具」还是「凶器」。这一本讲技术,也讲边界。

1
HTTP 基础请求/响应、状态码、Cookie——爬虫的地基
2
请求库Requests/HTTPX、会话、超时重试、代理
3
解析XPath、CSS 选择器、BeautifulSoup——网页变数据
4
动态网页JS 渲染、Playwright/Selenium、等待策略
5
API 抓取抓包、JSON 接口、Token——更高效的路
6
清洗存储去重、清洗、入库、调度——数据落地
7
反爬对抗UA/IP 限制/验证码——合规地「优雅爬取」
8
分布式Scrapy、分布式队列、增量抓取——规模化
9
合规红线Robots、个保法、著作权——爬虫的边界
10
项目实战从零搭一个新闻采集系统——完整流程
🧙
周师傅

记住一句话:爬虫的本质,是「模拟浏览器的行为,自动化地获取公开数据」——你手动能看到的公开页面,程序也能;你手动需要登录才能看的,程序一样需要授权。走,第一站,从最底层的 HTTP 开始。

第 1 站

HTTP 基础:爬虫的地基

请求/响应 · 状态码 · Cookie/Session · HTTPS

浏览器和服务器怎么说话?爬虫就是在「模拟这套对话」——所以 HTTP 是爬虫的第一课,也是理解「反爬」的前提。

🧙
周师傅

HTTP 就两件事:请求(Request)——客户端说「我要什么」;响应(Response)——服务器给「你要的东西 + 状态码」。

  • 请求方法:GET(取数据)、POST(提交数据)——爬虫 90% 用 GET。
  • 请求头(Headers):User-Agent(我是谁)、Cookie(我的身份)、Referer(我从哪来)——反爬的「第一道检查点」。
  • 状态码:200 成功、301/302 重定向、403 拒绝访问(被反爬了!)、404 不存在、429 请求太频繁(限流了!)、500 服务器错。
  • 会话(Session/Cookie):服务器靠 Cookie 认人——登录后带着 Cookie 才能访问需要身份的页面。

HTTPS:加密传输(第三本密码学讲过的 TLS)——爬虫一样抓,因为是「客户端解密后」的数据。

一次 HTTP 请求的「解剖」
GET /api/products?page=2 HTTP/1.1        ← 请求行:方法 + 路径 + 协议
Host: shop.example.com                    ← 请求头:目标主机
User-Agent: Mozilla/5.0 ...               ← 我是谁(爬虫常伪装成浏览器)
Cookie: session=abc123; token=xyz         ← 我的身份凭证
Referer: https://shop.example.com/list    ← 我从哪个页面来的

HTTP/1.1 200 OK                           ← 状态行:成功
Content-Type: application/json            ← 响应头:数据类型
{ "products": [{"name":"手机","price":2999}] }   ← 响应体:数据!

【状态码速查(爬虫版)】
  200  OK                 抓到了!
  301/302 重定向          自动跟随(requests 默认会)
  403  禁止访问           被反爬拦了(第7站)
  404  不存在             页面没了/URL 写错
  429  请求过多           太快了!要限速(第7站)
  500  服务器错误          对方挂了,稍后重试

【Cookie vs Session】
  Cookie:客户端存的「小纸条」(身份凭证)
  Session:服务端记的「账本」(你的状态)
  登录后服务器发 Cookie → 爬虫带着它访问受限页面

【浏览器 DevTools 是爬虫的第一工具】
  F12 → Network 面板:看每个请求的 Headers/参数/响应
  → 抓包是后面第 5 站的基础

HTTP 术语

  • 请求 / 响应:客户端要什么 / 服务器给什么——一次对话。
  • GET / POST:取数据 / 提交数据——两种基础方法。
  • 请求头:User-Agent / Cookie / Referer——反爬的第一检查点。
  • 状态码:200 / 403 / 429——爬虫的「体检报告」。
  • Cookie / Session:身份凭证 / 服务端状态——登录态的钥匙。
  • HTTPS:加密传输——不影响爬虫(解密后取数)。
  • DevTools Network:浏览器抓包面板——爬虫的第一工具。

本站收获:HTTP = 请求(说我要什么)+ 响应(给我数据+状态码)+ Cookie(我是谁)。会看 DevTools 的 Network 面板,爬虫就入门一半。

第 2 站

请求库:Requests / HTTPX

requests · 会话保持 · 超时重试 · 代理

Python 里发 HTTP 请求,requests 是事实标准;HTTPX 是支持异步的新一代。这一站,写爬虫的「手」。

🧙
周师傅

爬虫的基本功:请求发得对 + 出错扛得住 + 频率控制好。Requests 三件套:

  • 参数与头:params 拼查询参数、headers 带浏览器 UA、cookies 带身份。
  • 会话保持:`requests.Session()` ——同一会话自动带 Cookie(登录后访问受限页)。
  • 健壮性:超时必设(不设 = 卡死)、失败重试、状态码检查。

再加 代理(Proxy):换 IP 绕频率限制(合规场景:如访问海外公开数据)——但注意:绕验证码/暴力换 IP 对抗反爬属于灰色地带,合规场景慎用(第 9 站讲边界)。

Requests 实战:抓取商品列表
import requests

# 会话保持(自动管理 Cookie)
s = requests.Session()
s.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0",
})

# 登录后拿 Cookie(示例:POST 表单)
s.post("https://example.com/login",
       data={"user": "demo", "pass": "***"}, timeout=10)

# 带参请求列表页
resp = s.get("https://example.com/api/products",
             params={"page": 2, "size": 50},
             timeout=10)
print(resp.status_code)      # 200
print(resp.json())           # JSON 直接解析

# 健壮性:超时 + 重试 + 状态码检查
def safe_get(url, retries=3):
    for i in range(retries):
        try:
            r = s.get(url, timeout=10)
            if r.status_code == 200:
                return r
            if r.status_code == 429:        # 限流了!
                time.sleep(5)               # 尊重限速,等一会
        except requests.Timeout:
            pass
        time.sleep(2 ** i)                  # 指数退避重试
    return None

【HTTPX(新一代)】
  import httpx
  client = httpx.Client(headers={...})
  async with httpx.AsyncClient() as ac:    # 异步并发!
      rs = await ac.get(url)
  → 高并发场景(第8站)比 requests 强

请求库术语

  • requests.Session:会话保持——Cookie 自动管理。
  • params / headers / cookies:查询参数 / 请求头 / 身份凭证。
  • timeout:超时设置——不设 = 进程卡死。
  • 指数退避重试:失败后 1s、2s、4s……重试——优雅重试。
  • 429 处理:限流时尊重对方——等一等再抓。
  • HTTPX:异步新一代——高并发抓取利器。
  • 代理(Proxy):换出口 IP——合规场景谨慎使用。

本站收获:请求 = Session 保持身份 + params/headers 配全 + 超时重试保稳 + 429 限速尊重对方。会发请求,爬虫就有「手」了——下一步是「看懂网页」。

第 3 站

解析:从网页到数据

XPath · CSS 选择器 · BeautifulSoup · 正则

抓下来的 HTML 是一堆标签字符串——怎么把「价格、标题、链接」提取成干净的数据?解析是爬虫的「眼睛」。

🧙
周师傅

解析三选一,按场景挑:

  • BeautifulSoup(bs4):好学好用,容错强——适合简单页面、快速上手。
  • lxml + XPath:快、精准——`//div[@class='price']` 直接定位,复杂页面首选。
  • 正则(re):终极兜底——结构化差/藏在 JS 字符串里时用。

核心思路:先找「定位锚点」(class/id/结构),再提取内容——和第八本数据清洗一个道理:先定位,再取值。

解析实战:三种武器对比
from bs4 import BeautifulSoup
from lxml import etree
import re

html = """
<div class="product">
  <h3 class="title">无线耳机</h3>
  <span class="price">¥299.00</span>
  <a href="/p/123">详情</a>
</div>
"""

# ① BeautifulSoup:CSS 选择器
soup = BeautifulSoup(html, "html.parser")
title = soup.select_one("h3.title").text          # 无线耳机
price = soup.select_one(".price").text            # ¥299.00

# ② lxml + XPath:精准定位
tree = etree.HTML(html)
price2 = tree.xpath("//span[@class='price']/text()")[0]

# ③ 正则:兜底
price3 = re.search(r"¥([\d.]+)", html).group(1)   # 299.00

【XPath 速查(爬虫必会)】
  //div[@class='price']      按 class 找
  //ul/li[position()=2]      第二个 li
  //a/@href                  取属性(链接)
  //h3//text()               取所有文本

【解析最佳实践】
  优先用 class/id 定位(页面结构调整时也好维护)
  优先 XPath/CSS(比正则稳),正则做兜底
  页面结构变了 → 解析器报错 → 更新选择器(爬虫的日常)

【反爬注意】
  有些网站用「字体反爬」(数字用特殊字体渲染,复制出来是乱码)
  → 了解即可,破解属于灰色地带——合规第一

解析术语

  • BeautifulSoup:友好解析库——CSS 选择器 / find 全家。
  • XPath:XML 路径语言——`//tag[@attr='v']` 精准定位。
  • CSS 选择器:`.class` / `#id` / `tag`——前端同款语法。
  • 正则:文本模式的终极兜底——结构化差时用。
  • 定位锚点:class/id/结构——解析的「瞄准镜」。
  • 页面结构变更:解析器失效——爬虫的「日常维护」。
  • 字体反爬:数字乱码——了解即可,不教破解。

本站收获:解析 = XPath/CSS 精准定位 + bs4 快速上手 + 正则兜底。网页变数据的关键一步——「先找锚点,再取值」。

第 4 站

动态网页:Playwright

JS 渲染 · Playwright/Selenium · 等待策略 · 无头模式

有些页面是「JS 渲染」的——requests 抓回来只有空壳,数据是浏览器执行 JS 后才出现的。这时候需要「真正的浏览器」上场。

🧙
周师傅

两种网页:

  • 静态渲染:HTML 里直接有数据——requests 就能抓(前两站)。
  • 动态渲染:数据靠 JS 异步加载(Ajax/渲染框架)——requests 拿到空壳。

解法:用浏览器自动化——Playwright(微软出品,新一代主流)或 Selenium(老牌):让真实浏览器打开页面、执行 JS、等数据加载完,再取内容。关键技巧:等待策略(等元素出现再抓,别抢跑)、无头模式(headless,不开窗口省资源)。

Playwright 实战:抓 JS 渲染页面
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/trending",
              timeout=30000)                      # 打开页面

    # 等待数据加载完成(关键!别抢跑)
    page.wait_for_selector(".item-card",
                           timeout=10000)         # 等元素出现

    # 提取数据
    items = page.locator(".item-card").all()
    for it in items[:5]:
        title = it.locator(".title").inner_text()
        print(title)
    browser.close()

【Playwright vs Selenium】
  Playwright:新、快、API 优雅、自动等待(推荐新项目)
  Selenium:老牌、生态广(老项目/兼容性)

【等待策略(三大类)】
  显式等待:等某个元素/条件出现(推荐,精准)
  隐式等待:固定轮询等待(简单)
  硬等待:time.sleep(最笨,别用!)

【反检测(了解)】
  无头浏览器特征、webdriver 标记 → 有些站会检测
  → 规避检测属于灰色地带——合规场景用 Playwright 的持久化上下文即可

【适用场景(合规)】
  公开动态页面、自己的系统自动化测试、登录态自己授权的采集

动态网页术语

  • 静态 vs 动态渲染:数据在 HTML 里 vs 数据靠 JS 加载。
  • Playwright / Selenium:浏览器自动化——动态页面的解法。
  • 无头模式(headless):不开窗口跑浏览器——省资源。
  • 等待策略:等元素出现再抓——显式等待是正道。
  • XHR/Fetch:JS 发起的异步请求——动态数据的来源。
  • 自动化测试同源:Playwright 也是前端测试工具——一举两得。

本站收获:动态页面 = 真实浏览器(Playwright)打开 + 显式等待 + 提取。requests 抓不到的,浏览器能——「能开浏览器的爬虫,才是完整的爬虫」。

第 5 站

API 抓取:更高效的路

抓包 · JSON 接口 · Token · 逆向基础

很多「动态网页」背后的真相:页面只是壳,数据来自一个 JSON 接口——直接抓接口,比开浏览器快一百倍。这一站教你「找到接口」。

🧙
周师傅

核心思路:浏览器能拿到数据,一定有个请求在拉数据——找到它,直接模拟它

  • 抓包:DevTools → Network → 筛选 XHR/Fetch → 找返回 JSON 的请求——这就是接口。
  • 看参数:URL 里的查询参数、请求头里的 Token/签名——照抄。
  • 直接请求:用 requests 模拟这个接口,JSON 直接解析——不用开浏览器!

进阶(了解层面):签名/加密参数(逆向)——有些接口参数是 JS 算出来的(如 sign=md5(...))。正规途径:看对方是否提供公开 API 文档——有文档就用文档,合规又省心。

抓包找接口的完整流程
【找接口三步】
① F12 → Network → 勾选 XHR
② 刷新页面 / 翻页 → 看 Network 里刷新的请求
③ 找到返回 JSON 的那个 → 复制 URL + Headers

【示例:找到了接口】
GET https://api.example.com/v1/news?page=2&size=20
Headers: x-token: eyJhbGciOiJIUzI1NiJ9...   # Token

→ requests 直接调:
import requests
r = requests.get("https://api.example.com/v1/news",
    params={"page": 2, "size": 20},
    headers={"x-token": "eyJhbGci..."})
data = r.json()          # 直接拿到结构化数据!
print(data["items"][0]["title"])

【比浏览器快在哪】
  Playwright:每个页面开浏览器 ≈ 1-3 秒
  直接抓 API:一个请求 ≈ 0.1 秒 → 快 10-30 倍!

【Token 获取(正规途径)】
  公开 API → 申请开发者 Key(官方文档最香)
  自己账号登录 → 自己授权范围内使用
  → 逆向破解签名 = 灰色地带,本手册不教

【接口友好的判断】
  有公开 API 文档的网站 → 用官方 API(首选!)
  没有文档但有稳定 JSON 接口 → 模拟请求(注意 Robots)
应用场景:新闻采集提速 20 倍

原来用 Playwright 抓新闻站:每个页面 2 秒,一天 1 万条要 6 小时。抓包发现网站有稳定的 JSON 接口(公开数据)→ 直接 requests 调接口 → 同样 1 万条只要 20 分钟,还不用开浏览器。**能走接口,绝不走浏览器**——这是爬虫的黄金法则。

API 抓取术语

  • 抓包:DevTools Network 看请求——找数据的「水管」。
  • XHR / Fetch:JS 发起的异步请求——动态数据的载体。
  • JSON 接口:直接返回结构化数据的 URL——爬虫的最爱。
  • Token / API Key:接口身份凭证——正规途径申请。
  • 官方 API 文档:优先用官方接口——合规又省心。
  • 逆向(了解):破解签名参数——灰色地带,不教。
  • 黄金法则:能走接口,绝不走浏览器。

本站收获:API 抓取 = 抓包找接口 + 模拟请求直接拿 JSON。比开浏览器快 10-30 倍——「能走接口,绝不走浏览器」是爬虫效率第一法则。

第 6 站

清洗存储:数据落地

清洗 · 去重 · 入库 · 调度 · 增量抓取

爬下来的数据是「毛坯」——脏、重复、格式乱。清洗去重后入库,才算真正「拥有」数据。这一站是第八本《数据治理》在爬虫场景的实战。

🧙
周师傅

数据落地四步:

  • 清洗:去空白、统一格式、类型转换(价格 "¥299.00" → 299.00)——第八本 Pandas 手艺直接复用。
  • 去重:同一个商品抓了 3 遍——按「唯一键」(URL/title)去重,或用布隆过滤器(Bloom Filter)海量去重省内存。
  • 入库:小数据 CSV/JSON;结构化数据 MySQL;海量/异构数据 MongoDB/ES(第十二本)。
  • 调度与增量:定时任务(每天抓一次)、增量抓取(只抓新增/更新的)——别每次都全量重爬,浪费资源也不礼貌。
清洗 → 去重 → 入库(实战)
import pandas as pd
import pymysql

raw_items = [{"title": " 无线耳机 ", "price": "¥299.00", "url": "/p/123"},
             {"title": "无线耳机",  "price": "299.00",  "url": "/p/123"}]  # 重复!

# ① 清洗:去空格、统一格式
df = pd.DataFrame(raw_items)
df["title"] = df["title"].str.strip()
df["price"] = df["price"].str.replace("¥", "").astype(float)

# ② 去重:按 URL 唯一键
df = df.drop_duplicates(subset=["url"])
print(len(df))                       # 1 条(重复的没了)

# ③ 入库 MySQL(唯一键防重复)
conn = pymysql.connect(host="localhost", user="root", password="***",
                       database="crawler")
cur = conn.cursor()
cur.executemany(
    "INSERT IGNORE INTO products(title, price, url) VALUES(%s,%s,%s)",
    df[["title", "price", "url"]].values.tolist())
# INSERT IGNORE:数据库层面再挡一道重复
conn.commit()

【增量抓取设计】
  定时任务(cron/APScheduler):每天 02:00 跑
  记录「上次抓取位置」→ 只抓新增/更新的
  URL 去重集合(Redis SET / Bloom Filter)——别重复抓

【存储选型】
  CSV/JSON   :小数据、调试期
  MySQL      :结构化、要查询(主流)
  MongoDB    :JSON 原样存、字段不固定
  ES         :要全文搜索(第12本 ELK 衔接)

数据落地术语

  • 清洗:去空格、统一格式、类型转换——第八本手艺。
  • 去重(唯一键):按 URL/title 去重——爬虫必须做。
  • Bloom Filter(布隆过滤器):海量去重的省内存神器。
  • 入库选型:CSV / MySQL / MongoDB / ES——按需求。
  • 增量抓取:只抓新增/更新的——别全量重爬。
  • 调度:定时任务——爬虫系统的「闹钟」。
  • INSERT IGNORE:数据库层防重复——双保险。

本站收获:数据落地 = 清洗(去脏)+ 去重(唯一键)+ 入库(选型)+ 增量(别浪费)。爬下来只是开始,洗干净存好才是「数据资产」。

第 7 站

反爬对抗:道高一尺

UA 检测 · IP 限制 · 验证码 · 频率控制

你爬得开心,网站方可不开心——反爬机制层出不穷。这一站讲「常见的反爬是什么」,以及「合规的应对姿势」:尊重规则、优雅爬取。

🧙
周师傅

先讲清楚立场:反爬的本质是网站保护自己资源的合理措施。这一站教的是「理解 + 合规应对」,不是「破解」。常见的反爬手段:

  • UA/请求头检测:爬虫的 User-Agent 一眼假 → 应对:模拟正常浏览器 UA(合规伪装,模拟真人访问)。
  • IP 频率限制:同一 IP 太快 → 应对:限速(放慢节奏,尊重对方)、合规代理。
  • 验证码:识别机器人 → 应对:减少触发(慢一点)、或用官方 API(不破解!)。
  • 登录墙:要登录才能看 → 应对:自己账号、自己授权范围。

最重要的「应对」其实是:判断值不值得爬——对方明显不想让你爬,就换个数据源或走官方渠道。

合规的「优雅爬取」清单
【优雅爬取五原则】
  ① 慢:单线程 + 随机延迟(2-5 秒),像真人
  ② 少:只抓需要的字段,不整站拖走
  ③ 有节制:设置每日总量上限
  ④ 看 Robots:先看 robots.txt(网站声明哪些不能爬)
  ⑤ 留身份:User-Agent 写明是采集器 + 联系方式(礼貌!)

【常见的反爬与「合规应对」对照】
  反爬手段            合规应对
  UA 检测            → 模拟真实浏览器 UA
  IP 限频(403/429) → 限速 + 指数退避(尊重对方)
  验证码             → 放慢触发;官方 API;换数据源
  登录墙             → 自己的账号 + 自己授权范围
  JS 加密            → 用 Playwright 正常渲染(非破解)

【限速示例(必须做)】
import time, random
for url in urls:
    fetch(url)
    time.sleep(random.uniform(2, 5))   # 随机延迟,像真人

【robots.txt 检查】
  https://example.com/robots.txt
  User-agent: *  /  Disallow: /private/   ← 别爬 /private/!

【红线(绝对不做)】
  ✗ 破解验证码绕过人机验证
  ✗ 暴力撞库/拖库
  ✗ 大规模抓取打瘫对方服务器(DDoS 级别)
  ✗ 爬取后商用侵权(第9站展开)
应用场景:被 403 之后的「冷静处理」

爬虫跑太快被 403 了。小哲的合规处理:① 检查 robots.txt(对方允许公开列表页)→ ② 把并发降到 1、加 3-5 秒随机延迟 → ③ UA 改成真实浏览器 → ④ 恢复抓取,且每日总量限制。对方没有再触发验证码——「慢而稳」才是长期主义。

反爬术语(理解层)

  • 反爬机制:UA 检测 / IP 限频 / 验证码 / 登录墙 / JS 加密——网站的自卫手段。
  • 合规应对:限速、随机延迟、真实 UA、尊重 Robots——模拟真人而非破解。
  • robots.txt:网站声明「哪些别爬」的协议——先看它。
  • 429 / 403:限流 / 拒绝——信号:你太快了或不该爬。
  • 指数退避:被限后递增等待——优雅重试。
  • 红线:破解验证码、撞库、打瘫服务器、商用侵权——绝对不做。

本站收获:反爬的合规应对 = 慢(限速)+ 少(只取所需)+ 尊重(Robots/官方 API)。记住:破解是捷径也是绝路——「优雅爬取」才能长期稳定。

第 8 站

分布式:Scrapy 规模化

Scrapy 框架 · Scrapy-Redis · 增量 · 布隆过滤

页面从 3000 涨到 300 万——单机串行抓不动了。这一站上框架:Scrapy 是爬虫的「工业标准」,配 Redis 就能分布式。

🧙
周师傅

Scrapy:Python 最成熟的爬虫框架——调度、下载、解析、管道、去重全内置,还自带异步并发。核心组件:

  • Spiders:写解析逻辑的地方(URL 生成 + 数据提取)。
  • Items / Pipelines:数据模型 / 清洗入库管道。
  • Downloader Middleware:请求中间件——代理、UA 池、重试。
  • 调度器 + 去重:请求队列 + URL 去重。

分布式:默认调度器在单机——换成 Scrapy-Redis:请求队列放 Redis,多台机器共享队列,谁有空谁抓——百万级页面的标配。去重用布隆过滤器(Bloom Filter)省内存。

Scrapy 项目结构与分布式
crawler_project/
├── spiders/
│   └── news_spider.py        # 解析逻辑
├── items.py                  # 数据模型
├── pipelines.py              # 清洗 + 入库
├── middlewares.py            # 代理/UA/重试
└── settings.py               # 配置

# news_spider.py(简化)
class NewsSpider(scrapy.Spider):
    name = "news"
    start_urls = ["https://example.com/news"]

    def parse(self, response):
        for item in response.css(".news-item"):
            yield {
                "title": item.css(".title::text").get(),
                "url": item.css("a::attr(href)").get(),
            }
        # 翻页
        next_page = response.css("a.next::attr(href)").get()
        if next_page:
            yield response.follow(next_page, self.parse)

【分布式改造(Scrapy-Redis)】
  settings.py:
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    REDIS_URL = "redis://crawler-redis:6379"
  → 请求队列和去重集合都放 Redis
  → 10 台机器跑同一个 spider:共享队列,谁空谁抓

【规模化要点】
  并发与延迟平衡:CONCURRENT_REQUESTS 适中(别打瘫对方)
  增量抓取:按时间标记,只抓新增
  去重:Redis SET / Bloom Filter(亿级 URL 不爆内存)
  监控:抓取量、失败率、入库量(第12本 ELK 衔接)
应用场景:300 万页面的分布式采集

新闻全站 300 万页面:单机 Scrapy 要 20 天。改造:Scrapy-Redis + 5 台机器共享队列 → 4 天跑完,且每台机器限速 2 req/s 不打扰对方;布隆过滤器去重 URL,内存只占原来的 1/10。增量任务每天只抓新增——「规模化但不野蛮」。

Scrapy 术语

  • Scrapy:爬虫工业标准框架——调度/下载/解析/管道全家。
  • Spider / Item / Pipeline:解析逻辑 / 数据模型 / 清洗入库。
  • Middleware:中间件——代理池 / UA 池 / 重试。
  • Scrapy-Redis:队列和去重放 Redis——分布式爬虫标配。
  • Bloom Filter:亿级 URL 去重的省内存方案。
  • 增量抓取:只抓新增——长期任务的正确姿势。
  • 并发节制:规模再大也要限速——别打瘫对方。

本站收获:规模化 = Scrapy 框架打底 + Redis 分布式共享队列 + 布隆过滤去重 + 增量抓取。爬得动 300 万页,但永远「节制」——规模和技术要匹配道德。

第 9 站

合规红线:爬虫的边界

Robots · 个保法 · 著作权 · 反不正当竞争

爬虫圈有句老话:「技术无罪,用法有罪」。这一站是最重要的一站——不是教你怎么爬更多,而是教你怎么「不踩雷」。

🧙
周师傅

合规四道线,从轻到重:

  • ① Robots 协议:网站声明「哪些别爬」的君子协定——遵守它,是爬虫的基本礼貌(虽非法律强制,但影响后续判断)。
  • ② 网站条款(ToS):注册时勾选的服务条款——写明「禁止抓取」的,爬了可能构成违约。
  • ③ 法律底线个保法(爬取个人信息需合法正当必要 + 告知同意)、著作权(内容版权属于作者/网站,商用要授权)、反不正当竞争(爬取后直接搬运竞争 → 可能违法)。
  • ④ 刑法红线:非法获取计算机信息系统数据罪——突破安全措施、情节严重,是刑事犯罪。

自检三问:公开数据吗?对方允许吗?用途正当吗?——三问全过,才动手。

爬虫合规自检清单
【动手前自检三问】
  ✅ 数据是公开的吗?(不需要登录/无安全措施)
  ✅ 对方允许吗?(robots.txt 允许 / ToS 没禁止 / 有官方 API 优先)
  ✅ 用途正当吗?(学习/研究/自有数据分析,非侵权商用)

【四道线(由轻到重)】
  ① Robots 协议:君子协定——先看再爬
  ② 服务条款:注册时勾选的契约——违约有责
  ③ 法律:个保法(个人信息)/ 著作权(内容版权)
          / 反不正当竞争(搬库竞争)
  ④ 刑法:非法获取计算机信息系统数据罪——突破防线+情节严重

【安全做法推荐(按优先级)】
  1️⃣ 官方 API(有文档就用文档——最合规!)
  2️⃣ 公开数据 + 慢速 + 尊重 Robots
  3️⃣ 数据购买 / 合作授权(商业场景首选)
  4️⃣ 自建数据 / 用户主动提供

【案例警示(了解)】
  · 爬取并公开他人个人信息 → 个保法处罚
  · 突破验证码/加密批量拖库 → 刑事风险
  · 爬取竞争对手数据直接搬运 → 反不正当竞争诉讼
  → 教训:技术越强,越要懂边界
应用场景:合规的竞品价格监控怎么做

小哲公司要做竞品价格监控——正规做法:① 查目标网站 robots.txt 是否允许 + 是否有公开 API 或数据合作通道 → ② 优先走官方开放接口或商务合作 → ③ 只取价格等公开字段、低频更新(每日一次)、限速 → ④ 数据仅内部分析,不公开搬运。合规的爬虫,一样能拿到数据,只是「姿势不同」。

合规术语

  • Robots 协议:网站声明的「禁爬清单」——君子协定。
  • ToS(服务条款):注册契约——禁止抓取条款有约束力。
  • 个保法:个人信息处理需合法正当必要——爬个人信息要谨慎。
  • 著作权:内容版权——商用需授权。
  • 反不正当竞争:搬运竞争数据——法律风险高。
  • 刑法红线:非法获取计算机信息系统数据罪——突破安全措施即高危。
  • 合规优先级:官方 API > 公开慢爬 > 数据合作 > 别爬。

本站收获:合规 = 自检三问(公开?允许?正当?)+ 四道线(Robots→ToS→法律→刑法)+ 优先官方 API。爬虫最强的能力不是技术,是「知道什么不该爬」。

第 10 站

项目实战:从零搭一个采集系统

架构 · Scrapy 实战 · 监控 · 学习路线

知识点齐了,怎么落地成「能用的系统」?这一站,把前面九站串成一个完整的「新闻舆情采集系统」——爬虫项目的标准形态。

🧙
周师傅

一个成熟的爬虫项目 = 六层架构:

  • ① 任务调度:定时触发(每天 02:00)、增量任务。
  • ② 抓取层:Scrapy 框架 + 限速 + 重试(公开数据)。
  • ③ 解析层:XPath/正则提取 + 反爬应对(合规)。
  • ④ 清洗层:去重 + 格式化(第八本手艺)。
  • ⑤ 存储层:MySQL 结构化 + 去重索引。
  • ⑥ 监控层:抓取量/失败率/入库量 + 告警(第十二本 ELK)。

学习路线:Requests 练手 → BeautifulSoup/XPath → Scrapy 框架 → 分布式 → 合规思维——一步一个脚印。

新闻采集系统架构 + 避坑清单
┌─ 调度 ─┐   ┌─ 抓取 ─┐   ┌─ 解析 ─┐   ┌─ 清洗 ─┐   ┌─ 存储 ─┐   ┌─ 监控 ─┐
│ APScheduler│ → │Scrapy  │ → │XPath   │ → │去重/格式│ → │MySQL   │ → │ELK/告警│
│ 每天02:00 │   │限速重试 │   │提取    │   │        │   │唯一索引 │   │抓取量  │
└─────────┘   └─────────┘   └─────────┘   └─────────┘   └─────────┘   └─────────┘

【最小可行版本(2 周)】
  Week1:requests + XPath 抓一个站点 → 清洗入库
  Week2:迁移到 Scrapy → 定时任务 → 监控告警
  → 先跑通再扩展(第十一本老教训)

【避坑清单(血泪)】
  ✗ 不设超时/重试(进程卡死一整夜)
  ✗ 不设限速(被 403/封 IP)
  ✗ 不去重(数据库重复爆炸)
  ✗ 不设增量(每天全量重爬,浪费+不礼貌)
  ✗ 不监控(爬挂了三天没人知道)
  ✗ 不查 robots(惹上官司的前奏)

【学习路线(3 个月)】
  第1月:HTTP + Requests + 解析(XPath/bs4)
  第2月:动态页面 Playwright + 接口抓取
  第3月:Scrapy 框架 + 分布式 + 一个完整项目
  + 始终贯穿:合规思维(第9站三问)
应用场景:舆情采集系统上线记

2 周上线:Scrapy 抓 3 个新闻源(公开 RSS/列表页,限速 1 req/3s)→ XPath 提取标题/正文/时间 → 清洗去重入库 MySQL → 每天 02:00 增量抓取 → 抓取量和失败率进 ELK 看板。分析师每天早上看最新舆情,采集系统自动运行三个月零故障——「小而稳,胜过炫而崩」。

实战术语

  • 六层架构:调度→抓取→解析→清洗→存储→监控——爬虫系统标准形态。
  • 最小可行(MVP):先单站点跑通,再扩展。
  • 限速 / 重试 / 超时:健壮性三件套——必设。
  • 增量与去重:长期运行的两大基石。
  • 监控告警:抓取量/失败率——爬虫也要「可观测」。
  • 学习路线:Requests → 解析 → Playwright → Scrapy → 分布式。
  • 合规贯穿:从第一天起带着边界意识写代码。

本站收获:实战 = 六层架构串全栈 + 超时重试限速保稳 + 增量去重保效率 + 监控保发现 + 合规保安全。爬虫项目做得好不好,一半看技术,一半看「克制」。

附录

知识点速查 + 工具链

实战前最后一页

爬虫知识点全景表

环节核心知识点一句话人话
HTTP 基础请求/响应、状态码、Cookie/Session、DevTools浏览器和服务器怎么说话
请求库requests、Session、超时重试、HTTPX爬虫的「手」
解析XPath、CSS 选择器、BeautifulSoup、正则网页变数据的「眼睛」
动态页面Playwright、Selenium、等待策略、无头模式开真浏览器抓 JS 渲染页
API 抓取抓包、JSON 接口、Token、官方 API能走接口绝不走浏览器
清洗存储清洗、去重、MySQL/MongoDB、增量抓取爬下来要洗要存
反爬应对限速、随机延迟、真实 UA、尊重 Robots慢而稳,优雅爬取
分布式Scrapy、Scrapy-Redis、Bloom Filter百万页面的规模化
合规红线Robots、个保法、著作权、刑法红线知道什么不该爬
项目实战六层架构、MVP、监控告警从代码到系统

工具链速查

用途工具
抓包看请求浏览器 DevTools Network / Fiddler / Charles
请求库requests(同步)/ HTTPX(异步)
解析BeautifulSoup + lxml(XPath)+ re
浏览器自动化Playwright(新)/ Selenium(老)
框架Scrapy(工业标准)+ Scrapy-Redis(分布式)
存储MySQL / MongoDB / Redis(去重队列)/ CSV
调度APScheduler / cron / Airflow(第九本老朋友)
监控ELK(第十二本)/ 简单告警脚本
HTTP 地基
请求 requests
解析 XPath
动态 Playwright
接口 抓包
落地 清洗存储
规模化 Scrapy
合规 红线 ⚖️
爬虫的本质,
是「模拟浏览器的行为,自动化地获取公开数据」。
技术本身是中性工具,怎么用决定它是「工具」还是「凶器」——
慢一点、少一点、尊重多一点,
能走官方 API 就不走弯路,
知道什么不该爬,比会爬什么更重要。
🕸️ 🌐 📥 🧩 🖥️ ⚡ 🗄️ 🛡️ ⚖️ 🚀 🌳
✌ 语言