使用 Python 爬取论坛而不触发反爬虫措施

发布: (2025年12月23日 GMT+8 09:03)
8 min read
原文: Dev.to

抱歉,我需要您提供要翻译的完整文本内容(除代码块和 URL 之外),才能为您进行翻译。请将文章的正文粘贴在这里,我会按照您的要求保留源链接、格式和技术术语,并将内容翻译成简体中文。

Scraping Forums Without Getting Flagged

我花了多年时间在论坛的缝隙中爬行——那些已经被遗忘、但只要仔细聆听仍在低声嗡鸣的老论坛,稍有好奇就会弹出验证码的前沿板块,只有在归档中才能复活的死社区,PHPBB 的伤痕,vBulletin 的幽灵,以及 Cloudflare 紧盯着你的每一步。它们都有一个共同点:想要知道有人在窥探,即使只是为了阅读。

核心思路

像人类一样抓取。
枯燥、重复、稍有分心。是人类,但那种没人注意到的类型。


1. 手动探索优先

  1. 在普通浏览器中打开论坛。
  2. 随意点击、滚动、翻页、查看用户资料。
  3. 打开 DevTools → Network 并重新加载一个主题帖。
  4. 观察:
    • 哪些请求会被触发,哪些不会?
    • 请求头中是否有轮换的 token?
    • Cookie 是否只在第一页出现?
    • 是否有隐藏的 POST 请求?
  5. 记录 每一条观察——不写代码,不做推理。反机器人系统是模式匹配器;你的任务是避开它们预期的模式。

2. 使用持久会话

import requests

session = requests.Session()
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept": "text/html,application/xhtml+xml",
    "Connection": "keep-alive"
})

# 第一次请求 = 握手(设置 cookie 等)
session.get("https://exampleforum.com/")

选定一个 User‑Agent 并 永远不要 在运行中更换。人类不会每隔几分钟就换浏览器。

3. 类人暂停

import time
import random

def human_pause(base: float = 3) -> None:
    """Sleep for a random interval that feels human."""
    time.sleep(base + random.uniform(0.5, 2.5))
  • 每一次有意义的请求之间调用 human_pause()
  • 如果你要抓取上百个主题,预计任务会花 数小时 而不是几分钟。

4. 随机化 URL 顺序

import random

thread_urls = list(collected_threads)   # pre‑collected set of URLs
random.shuffle(thread_urls)            # jump around, don’t go sequentially

人类会从主题 7 → 主题 2 → 一个用户资料 → 再回到首页。模仿这种行为。

5. 解析前的延迟

response = session.get(url)
human_pause()                     # pause **before** you touch the DOM
soup = BeautifulSoup(response.text, "html.parser")

瞬间解析是明显的信号。稍作停顿会让抓取器看起来更“思考”。

6. (可选)Selenium / Playwright

  • 仅在论坛大量依赖 JavaScript 时使用
  • 关闭无头模式,设置真实的窗口尺寸,并在操作之间加入 human_pause()
  • 大多数传统论坛都是纯 HTML → requests + BeautifulSoup 已足够。

7. 尊重 robots.txt

虽然它不是法律,但它告诉你站点期望哪些页面被慢速爬取。

  • 宽松 → 当作“慢速、枯燥的用户”。
  • 严格 → 假设监控更严,格外小心。

8. 检测软封锁

常见迹象:

  • 空响应
  • 登录重定向
  • 隐藏的 captcha HTML
  • HTTP 200 但正文异常短
if "captcha" in response.text.lower():
    raise RuntimeError("Soft blocked")

遇到封锁时:

  1. 暂停(几分钟到几小时)。
  2. 不要 激进地轮换 IP 或 User‑Agent。
  3. 稍后以更慢的速度恢复。

9. 避免高负载接口

  • 搜索 接口监控严格,视为“仅限人类”。
  • 只使用分类页、索引页和最近主题列表。

10. 将状态持久化到数据库

import sqlite3

conn = sqlite3.connect("forum.db")
c = conn.cursor()
c.execute('''
CREATE TABLE IF NOT EXISTS posts (
    thread_id TEXT,
    post_id   TEXT,
    content   TEXT,
    timestamp TEXT
)
''')
conn.commit()
  • 将每条帖子保存到数据库,以便后续恢复或增量抓取。

Source:

11. 变更你的抓取时间表

  • 不要像 cron 任务一样每晚 02:00 AM 固定抓取。
  • 随机跳过某些天,改变开始时间,插入额外的暂停。
  • 人类的浏览模式本身就是不规律的。

12. 精简请求负载

  • 忽略头像、签名、徽章,除非你真的需要它们。
  • 避免下载图片——图片会增加带宽消耗并提升被察觉的风险。
  • 通常只有主题的前几页包含有价值的讨论内容。

13. 需要时的登录抓取

  • 只使用 一个 已登录会话;在已登录状态下不要轮换 IP 或 User‑Agent。
  • 尊重账户的速率限制——速度要 比匿名访客慢得多

14. 最小化主题抓取示例

from bs4 import BeautifulSoup

def scrape_thread(url: str):
    response = session.get(url)
    human_pause()

    soup = BeautifulSoup(response.text, "html.parser")
    posts = soup.select(".post")          # adjust selector to the forum's markup

    data = []
    for post in posts:
        post_id   = post.get("data-post-id")
        content   = post.select_one(".content").get_text(strip=True)
        timestamp = post.select_one(".date").get_text(strip=True)

        data.append((url, post_id, content, timestamp))

        # Store immediately
        c.execute(
            "INSERT INTO posts (thread_id, post_id, content, timestamp) VALUES (?,?,?,?)",
            (url, post_id, content, timestamp)
        )
    conn.commit()
    return data

TL;DR

  1. 先手动观察 再写代码。
  2. 使用 单一持久会话 并配上稳定的 User‑Agent。
  3. 在所有地方 插入类人暂停
  4. 随机化 URL 顺序 与导航模式。
  5. 边爬边将数据持久化 到 SQLite(或其他数据库)。
  6. 遵守 robots.txt,避免搜索,并且变换你的爬取时间表。
  7. 被封锁时,放慢速度 而不是立刻升级。
content = post.select_one(".content")
if content:
    data.append(content.get_text(strip=True))

return data

注意缺少的内容:没有并发、没有重试、没有提速技巧。这些以后再说,甚至可能永远不需要。
这会发生,即使你把一切都做对了。

不要立刻升级。只改变时间安排。延长等待时间,缩小爬取范围,甚至完全暂停。频繁更换 IP 或 User‑Agent 只会让你更显眼。有时最正确的做法就是保持沉闷。

反爬系统并不聪明——它们很焦虑。它们寻找速度、规律、流量和持久性。去掉这些信号,你就会消失在无尽刷屏的人群噪音中。

目标不是隐形,而是不重要。安静、缓慢、对任何人都不构成困扰。

爬取论坛并不是要突破技术壁垒,而是对一个想装作不在乎的系统进行社会工程。像一个无关紧要的人一样行动,你就会被放任自流。观察、暂停、打乱、阅读、等待、重复。

这就是用 Python 爬取论坛而永不触发反爬措施的方式。慢慢来,悄悄来,耐心来。带着一种“我永远也完成不了,但我不在乎,因为过程才是意义”的耐心。

Back to Blog

相关文章

阅读更多 »