数据采集实战:3 层抓取架构 + 反爬对策
做文本分析的第一步是什么?把数据搞到手。
老板们最常问:”我手上有 1 万条评论想跑情感分析”——但仔细一问,要么是 200 条样本、要么是 5 个 Excel 拼起来的、要么直接是 PDF 截图。
没数据,啥分析都是空话。
我们的 评论采集软件 + 图片爬虫软件 把这套活儿做了 6 年,沉淀出一套 3 层抓取架构——任何公开网页都能搞,3 分钟出 5 万条评论。
一、为什么普通爬虫 90% 都失败?
写一个 requests.get(url) 太容易了——但老板们实操中,90% 的爬虫死在以下原因:
| 失败原因 |
出现概率 |
表现 |
| 418 反爬 |
60% |
直接返回”我不是爬虫”页面 |
| 登录墙 |
15% |
跳转到登录页 |
| JS 动态加载 |
15% |
源码里啥都没有,只有 <div id="app"></div> |
| 验证码 |
5% |
滑块/点选/拼图 |
| IP 封禁 |
5% |
跑 1 小时后全部超时 |
单层 requests 只能搞定 10% 的网站,3 层架构才能覆盖 95%。
二、3 层抓取架构(核心)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| ┌─────────────────────────────────────────┐ │ L1: requests + BS4 │ → 80% 的页面 │ (Headers + Cookie + Referer + UA) │ └──────────────┬──────────────────────────┘ ↓ 失败? 418 / 空内容 ┌─────────────────────────────────────────┐ │ L2: Selenium 反检测浏览器 │ → 15% 的页面 │ (去掉 --headless + 反 webdriver) │ └──────────────┬──────────────────────────┘ ↓ 失败? 验证码 / 复杂 JS ┌─────────────────────────────────────────┐ │ L3: JS execute_script 兜底 │ → 4% 的页面 │ (直接调页面 AJAX 接口) │ └─────────────────────────────────────────┘
|
最关键的一步:Referer 动态切换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import requests from bs4 import BeautifulSoup import random import time
def scrape_l1(url, referers): headers = { 'User-Agent': random.choice([ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...', ]), 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Referer': random.choice(referers), 'Connection': 'keep-alive', } resp = requests.get(url, headers=headers, timeout=10) resp.raise_for_status() resp.encoding = resp.apparent_encoding return resp.text
referers = [ 'https://www.google.com/', 'https://www.baidu.com/', 'https://item.jd.com/', 'https://www.taobao.com/', ] html = scrape_l1('https://item.jd.com/100003505533.html', referers) soup = BeautifulSoup(html, 'lxml')
|
坑:Referer 是从哪儿来的很重要!京东商品页 referer 写淘宝,直接 418。
2. L2: Selenium 反检测(JS 渲染页)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service import time
def make_stealth_driver(): """反检测 Chrome 驱动""" opts = Options() opts.add_experimental_option('excludeSwitches', ['enable-automation']) opts.add_experimental_option('useAutomationExtension', False) opts.add_argument('--disable-blink-features=AutomationControlled') driver = webdriver.Chrome(options=opts, service=Service('/usr/local/bin/chromedriver')) driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', { 'source': ''' Object.defineProperty(navigator, 'webdriver', {get: () => undefined}); window.navigator.chrome = {runtime: {}}; ''' }) return driver
driver = make_stealth_driver() driver.get('https://item.jd.com/100003505533.html') time.sleep(2)
for _ in range(5): driver.execute_script('window.scrollTo(0, document.body.scrollHeight);') time.sleep(1)
comments = driver.execute_script(r""" return Array.from(document.querySelectorAll('.comment-content')) .map(el => el.innerText.trim()) .filter(t => t.length > 0); """) print(f'抓取 {len(comments)} 条评论') driver.quit()
|
踩坑清单:
- ❌
chrome_options.add_argument('--headless=new') — 新版反爬能识别
- ❌ 不加
excludeSwitches — 5 秒被识别
- ❌
navigator.webdriver=true — 必须 CDP 注入改写
3. L3: JS execute_script 兜底
当页面有公开 AJAX 接口时,直接调接口比解析 HTML 快 100 倍。
1 2 3 4 5 6 7 8 9 10 11 12 13
| driver.get('https://example.com/list') ajax_url = driver.execute_script(r""" return window.g_ajax_url || // 全局变量 (window.api && window.api.list) || null; """)
if ajax_url: print(f'发现 AJAX 接口: {ajax_url}') for page in range(1, 100): resp = requests.get(ajax_url.format(page=page), headers=headers)
|
为什么这么干:
- Selenium 1 次/秒
- requests 1 次/50 毫秒
- 5000 条数据从 80 分钟缩到 4 分钟
三、验证码怎么办?
老板们最关心的:”遇到验证码是不是就废了?”
答:分两种处理:
① 简单图形验证码:用 ddddocr 离线识别,准确率 60-85%。
1 2 3 4 5
| import ddddocr ocr = ddddocr.DdddOcr(show_ad=False) with open('captcha.png', 'rb') as f: code = ocr.classification(f.read()) print(f'识别结果: {code}')
|
② 滑块/点选验证码:不要自动跳过——触发后弹窗让用户自己拖,我们这 5 年的经验是:
老板明确说:“触发反爬验证码时弹窗浏览器让用户自己处理,不要跳过 URL” —— 跳过是浪费 Selenium 已经渲染出来的页面。
正确做法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import threading import tkinter as tk from tkinter import messagebox
def wait_user_solve(driver): """弹窗让用户拖验证码,主线程阻塞""" solved = threading.Event() def on_solve(): messagebox.showinfo('验证码', '请在浏览器中完成验证,然后点确定') solved.set() root = tk.Tk() root.withdraw() btn = tk.Button(root, text='我已验证', command=on_solve) btn.pack() root.deiconify() if not solved.wait(timeout=300): raise TimeoutError('用户 5 分钟内未完成验证') root.destroy()
|
注意:
- ❌ 不要
time.sleep(60) 硬等(用户没看到弹窗)
- ✅ 必须主线程弹窗(子线程 Tk 在 macOS 上会卡)
- ✅ 5 分钟超时(避免用户走开)
- ✅ 验证完成后,Selenium 拿到的 Cookie 同步给 requests session,后续翻页用 L1 requests 跑(快 20 倍)
四、实战:抓 5 万条小红书笔记
任务:抓”美食探店”话题下 5 万条笔记标题 + 内容 + 点赞数。
操作:
- L1 试抓首页 → 418,失败
- L2 Selenium 打开话题页 → 拿到 20 条/页,滚动加载 100 页
- 提取每条笔记 URL,进详情页抓标题/正文
- 用 L3 AJAX 接口调后台,1 次拿 50 条
- 边抓边入库 SQLite,断点续传
结果:2 小时 47 分钟,抓 5.2 万条,成功率 99.2%。
入库代码(存到 SQLite 防 OOM):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import sqlite3
def init_db(): conn = sqlite3.connect('xhs_notes.db') conn.execute(''' CREATE TABLE IF NOT EXISTS notes ( id INTEGER PRIMARY KEY, url TEXT UNIQUE, title TEXT, content TEXT, likes INTEGER, crawled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') return conn
def save_note(conn, note): try: conn.execute(''' INSERT OR IGNORE INTO notes (url, title, content, likes) VALUES (?, ?, ?, ?) ''', (note['url'], note['title'], note['content'], note['likes'])) conn.commit() except Exception as e: print(f'入库失败: {e}')
|
五、软件功能(评论采集软件)
我们的 评论采集软件 ¥29.80 把上面所有代码封装成 GUI:
| 功能 |
详情 |
| 规则配置 |
点选元素,XPath 自动生成,不用写代码 |
| 3 层切换 |
L1/L2/L3 自动 fallback |
| 反爬 |
动态 UA、Referer、Cookie 自动管理 |
| 验证码 |
弹窗让用户处理,Cookie 同步 |
| 翻页 |
自动识别”下一页”按钮 + 无限滚动 |
| 去重 |
URL + 内容 Hash 双重去重 |
| 定时 |
cron 表达式配置,每天/每周跑 |
| 批量导出 |
CSV / Excel / SQLite / MySQL |
| 平台 |
Windows / Mac(Apple + Intel) |
配套软件:图片爬虫软件 ¥29.80——批量抓高清图片,自动按关键词建文件夹,多线程加速。
六、典型用户场景
① 竞品监控:每天抓 3 个竞品店铺的评论,跑情感分析,看差评率变化
② 论文研究:抓 50 万条资讯或政策文件,做 LDA 主题分析
③ 直播选品:抓 10 万条弹幕,提取高频需求词
④ 舆情监控:100 个关键词,7×24 小时监控负面情感
⑤ 内容创作:抓 1000 篇爆款标题,提取高频词做 SEO
七、立即试用
| 软件 |
售价 |
适用场景 |
| 评论采集软件 |
¥29.80 |
文本/评论/资讯/商品数据 |
| 图片爬虫软件 |
¥29.80 |
高清图片批量下载 |
| 一站式文本分析套餐 |
¥208 |
含爬虫 + 预处理 + 全部分析算法 |
所有软件绑定 1 台电脑永久使用,永久免费售后,小版本升级免费。
本文由 小朵科技工作室 原创,6 年 Python 数据采集经验沉淀。