第二章:数据采集系统

第二章:数据采集系统

数据是新时代的石油。采集、清洗、销售数据的生意,底层逻辑和石油行业惊人地相似:开采成本决定利润率,数据独占性决定定价权。


2.1 Web Scraping 的本质

Web Scraping 是自动化地从网页上提取结构化数据。你在浏览器里手动看的东西,Scraper 用代码批量获取。

三种数据获取方式

HTML 解析:直接下载网页的 HTML,用正则表达式或解析库提取数据。最快,成本最低,但很多现代网站是 JavaScript 渲染的,HTML 里没有数据。

无头浏览器(Headless Browser):用真实的浏览器引擎(Chromium),模拟用户操作,等待 JavaScript 渲染完成后再提取数据。速度较慢,资源消耗大,但能处理几乎所有网站。

API 逆向工程:网页加载时,浏览器会调用后端 API 获取数据。通过抓包分析这些 API 请求,直接调用 API 获取数据,比解析 HTML 更稳定、更高效。


2.2 核心技术栈

Scrapy(Python)

Scrapy 是最成熟的 Python 爬虫框架,适合大规模、高并发的采集任务:

import scrapy

class ProductSpider(scrapy.Spider):
    name = 'products'
    
    def start_requests(self):
        urls = ['https://example.com/products/page/1']
        for url in urls:
            yield scrapy.Request(url, callback=self.parse)
    
    def parse(self, response):
        # 提取产品数据
        for product in response.css('.product-item'):
            yield {
                'name': product.css('h2.title::text').get(),
                'price': product.css('.price::text').get(),
                'url': product.css('a::attr(href)').get(),
            }
        
        # 翻页
        next_page = response.css('a.next::attr(href)').get()
        if next_page:
            yield response.follow(next_page, callback=self.parse)

Scrapy 的核心优势:内置并发控制、自动遵守 robots.txt(可配置关闭)、内置中间件系统(方便集成代理轮换)、Item Pipeline(数据处理管道)。

Playwright(Node.js / Python)

Playwright 是微软开发的现代浏览器自动化工具,支持 Chromium、Firefox、WebKit:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    context = browser.new_context(
        user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        # 通过代理
        proxy={'server': 'http://user:pass@gate.smartproxy.com:10000'}
    )
    page = context.new_page()
    
    page.goto('https://www.amazon.com/dp/B08N5WRWNW')
    
    # 等待价格元素加载
    page.wait_for_selector('.a-price-whole')
    
    price = page.locator('.a-price-whole').first.text_content()
    title = page.locator('#productTitle').text_content()
    
    print(f"Product: {title.strip()}, Price: ${price}")
    
    browser.close()

Puppeteer(Node.js)

Puppeteer 是 Google 开发的 Chrome 自动化工具,比 Playwright 早,但 Playwright 的多浏览器支持和 API 设计更现代。

Requests + BeautifulSoup(入门)

对于简单静态网站,最轻量的方案:

import requests
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
    'Accept-Language': 'en-US,en;q=0.9',
}

response = requests.get('https://example.com/list', headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')

for item in soup.select('.item-row'):
    name = item.select_one('.item-name').text.strip()
    price = item.select_one('.item-price').text.strip()
    print(f"{name}: {price}")

2.3 反采集机制与应对

现代网站有多种反爬策略,理解它们才能有效应对。

Rate Limiting(速率限制)

检测方式:同一 IP 短时间内请求过多,返回 429 Too Many Requests。

应对方式

  • 代理轮换(每隔几个请求换 IP)
  • 随机延迟(time.sleep(random.uniform(1, 3))
  • 模拟人类行为节奏(不要每秒精确发 1 个请求,人类不是这样的)

User-Agent 检测

检测方式:识别 Python-requests/2.x 这样的默认 UA,或者 HeadlessChrome 特征。

应对方式

from fake_useragent import UserAgent
ua = UserAgent()
headers = {'User-Agent': ua.random}

IP 声誉过滤

检测方式:对比 IP 是否在已知数据中心 IP 段,或已知的恶意 IP 黑名单。

应对方式:使用住宅代理或移动代理(见第一章)。

Cloudflare Bot Management

Cloudflare 的反爬层级

  1. 基础 JS Challenge:注入 JavaScript,检查浏览器环境,生成挑战响应。普通 Requests 库无法通过,需要 Playwright/Puppeteer。
  2. Cloudflare Turnstile:比 reCAPTCHA 更友好的 CAPTCHA,但对无头浏览器有额外检测。
  3. Bot Management:企业版,行为分析、TLS 指纹、HTTP/2 指纹,识别率极高。

应对工具

  • cloudscraper:Python 库,能绕过基础 Cloudflare JS Challenge
  • Playwright + 浏览器指纹伪造:绕过中等难度的 Cloudflare
  • Bright Data Web Unlocker / Scrapingbee / Zyte API:付费服务,将绕过工作外包
# 使用 cloudscraper
import cloudscraper

scraper = cloudscraper.create_scraper()
response = scraper.get('https://cloudflare-protected-site.com/')
print(response.text)

CAPTCHA

类型:reCAPTCHA v2(图片选择)、reCAPTCHA v3(无感知,给行为打分)、hCaptcha、Arkose Labs。

CAPTCHA 解决服务

  • 2Captcha:人工解决,$0.5-3/1000 个,延迟 10-30 秒
  • Anti-Captcha:类似 2Captcha
  • CapSolver / NopeCHA:AI 自动解决,更快更便宜,但某些类型成功率低
  • Capsolver API 示例
import capsolver
capsolver.api_key = "YOUR_API_KEY"

solution = capsolver.solve({
    "type": "ReCaptchaV2Task",
    "websiteURL": "https://example.com",
    "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
})

print(solution['gRecaptchaResponse'])

浏览器指纹检测

网站通过收集浏览器的各种特征来识别是否是真实用户:

  • Canvas 指纹:渲染一个隐藏的 Canvas 元素,哈希渲染结果(不同设备/驱动结果不同)
  • WebGL 指纹:GPU 信息
  • 字体列表:系统安装的字体集合
  • 时区 + 语言:是否与 IP 地理位置匹配
  • Screen 分辨率 + Color Depth
  • Plugins 列表
  • AudioContext 指纹

应对方式:反检测浏览器(Multilogin、AdsPower,详见第三章),或使用 Playwright 的 stealth 插件:

const { chromium } = require('playwright');
const { stealth } = require('playwright-extra-plugin-stealth');

// playwright-extra 添加 stealth 功能
const playwright = require('playwright-extra');
playwright.use(stealth());

const browser = await playwright.chromium.launch({ headless: true });

2.4 大规模采集架构

单机爬虫能处理的量有限。对于每天需要采集数百万个页面的任务,需要分布式架构。

基础架构组件

任务队列

  • Redis + Scrapy-Redis:将待爬 URL 存入 Redis,多个爬虫节点从 Redis 取任务,避免重复爬取
  • RabbitMQ / Kafka:适合更复杂的任务调度(优先级队列、延迟任务)
  • Celery:Python 任务队列框架,与 Redis/RabbitMQ 配合使用
# Scrapy-Redis 分布式配置
# settings.py
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
REDIS_URL = "redis://your-redis-host:6379"
SCHEDULER_PERSIST = True  # 重启后继续未完成的任务

代理中间件

# middlewares.py
class RotatingProxyMiddleware:
    PROXY_LIST = [
        'http://user1:pass@proxy1.example.com:8000',
        'http://user2:pass@proxy2.example.com:8000',
        # ...
    ]
    
    def process_request(self, request, spider):
        request.meta['proxy'] = random.choice(self.PROXY_LIST)

存储层

  • PostgreSQL:结构化数据,支持复杂查询
  • MongoDB:半结构化数据,schema 灵活
  • S3 / Cloudflare R2:原始 HTML 存档(便宜,按 GB 计费)
  • Elasticsearch:如果需要全文搜索

部署方案

Docker + Kubernetes:每个爬虫节点是一个 Docker 容器,Kubernetes 管理扩缩容:

# kubernetes deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: scrapy-worker
spec:
  replicas: 10  # 10 个并发爬虫节点
  selector:
    matchLabels:
      app: scrapy-worker
  template:
    spec:
      containers:
      - name: scrapy
        image: your-scrapy-image:latest
        env:
        - name: REDIS_URL
          value: "redis://redis-service:6379"
        - name: PROXY_API_KEY
          valueFrom:
            secretKeyRef:
              name: proxy-credentials
              key: api-key

Apify Cloud:爬虫即服务平台,可以直接在上面部署 Scrapy/Playwright 爬虫,按执行时间计费。是快速验证商业模式的好选择,不需要自己管理基础设施。


2.5 数据清洗与结构化

采集到的原始数据通常需要大量清洗才能使用。

常见清洗任务

import re
from decimal import Decimal

def clean_price(raw_price: str) -> Decimal:
    """$1,299.99 → Decimal('1299.99')"""
    cleaned = re.sub(r'[^\d.]', '', raw_price)
    return Decimal(cleaned) if cleaned else None

def clean_text(raw: str) -> str:
    """移除多余空白,标准化编码"""
    if not raw:
        return ''
    return ' '.join(raw.split()).strip()

def extract_rating(raw: str) -> float:
    """'4.5 out of 5 stars' → 4.5"""
    match = re.search(r'(\d+\.?\d*)\s*out of', raw)
    return float(match.group(1)) if match else None

def normalize_url(url: str, base_url: str) -> str:
    """把相对 URL 转换为绝对 URL"""
    from urllib.parse import urljoin
    return urljoin(base_url, url)

数据去重

import hashlib

def generate_url_hash(url: str) -> str:
    """生成 URL 的哈希值,用于去重"""
    # 先标准化 URL(去掉 utm 参数等)
    from urllib.parse import urlparse, urlencode, parse_qs
    parsed = urlparse(url)
    params = {k: v for k, v in parse_qs(parsed.query).items() 
              if k not in ['utm_source', 'utm_medium', 'utm_campaign']}
    clean_url = parsed._replace(query=urlencode(params, doseq=True)).geturl()
    return hashlib.md5(clean_url.encode()).hexdigest()

2.6 数据变现的商业模式

采集数据后,如何赚钱?

数据 API(最高利润)

将数据封装成 API,按调用次数或订阅收费。

RapidAPI 平台

  • 在 RapidAPI 上发布 API,平台帮你处理计费和分发
  • 你定价(免费/按次/订阅),RapidAPI 抽成约 20-30%
  • 成功的 API 每月可以带来 $500-$10,000+ 被动收入

案例:Amazon Product Data API,让开发者用 API 获取 Amazon 商品信息,而不用自己爬。RapidAPI 上这类 API 的订阅价格 $50-500/月。

数据集出售

直接出售数据集(CSV、JSON、数据库导出):

平台

  • Datarade:B2B 数据市场,适合卖高价值商业数据
  • Snowflake Data Marketplace:在 Snowflake 生态内出售数据
  • AWS Data Exchange:亚马逊的数据市场
  • Kaggle:社区驱动,免费为主,适合建立数据集品牌

定价

  • 一次性数据集(历史快照):$50-$50,000
  • 数据订阅(持续更新):$500-$10,000/月

数据 SaaS(最高壁垒)

把数据做成工具,用户通过 SaaS 界面使用:

案例

  • SimilarWeb:把网站流量数据做成 SaaS,$167/月起
  • Crunchbase:把创业公司数据做成 SaaS,$29/月起
  • Glassdoor:把公司评价数据做成招聘服务
  • Zillow:把房产数据做成房地产搜索引擎

自己能做的垂直版本

  • 某城市的租房价格追踪工具(爬链家/贝壳,做成本地服务)
  • 某电商类目的竞品价格追踪工具($99-499/月 SaaS)
  • 某行业的招聘信息整合(职位数据 + 分析)

2.7 合法性评估框架

在开始采集之前,评估法律风险:

问五个问题

  1. 网站有 robots.txt 吗?你采集的 URL 在 Disallow 列表里吗?

    • 违反 robots.txt 不违法(在美国),但可能构成违反 ToS 的证据
  2. ToS 是否明确禁止自动化采集?

    • 违反 ToS 可能构成合同违约,可能面临民事诉讼
    • 公开数据(不需要登录)的 ToS 限制法律效力有争议
  3. 数据包含个人信息吗?

    • 采集姓名、邮件、电话等 PII(个人身份信息),在 GDPR 管辖下可能需要合法基础
    • 公开社交媒体的公开个人信息:法律灰色区,不同国家判决不同
  4. 你是否需要登录才能获取数据?

    • 登录后采集几乎肯定违反 ToS,且受 CFAA 保护(未授权访问)
  5. 你的采集是否影响网站正常运行?

    • 占用过多服务器资源,可能构成 DoS 攻击(违法)

最安全的数据来源

  • 公开的政府数据集
  • CC 许可的数据集
  • 网站明确授权的数据 API

2.8 Scraping as a Service 商业模式

不卖数据,而是卖采集能力。

Apify:爬虫 SaaS 市场,开发者可以在上面发布爬虫(Actor),用户付费使用:

  • Apify Store:类似 App Store,用户搜索"Amazon Scraper"并订阅
  • 开发者抽成:70%(Apify 抽 30%)
  • 热门 Actor 每月可以赚 $1,000-$10,000

Zyte(前 Scrapinghub)

  • 代理 + 智能爬虫 + 数据提取全套服务
  • 企业客户为主
  • 他们的 Zyte API 内置了自动绕过反爬机制

ScrapingBee / ScraperAPI

  • 代理 + 无头浏览器 + CAPTCHA 解决
  • 按 API 调用次数收费
  • 面向不想自己维护爬虫基础设施的开发者

自建 Scraping SaaS: 如果你在某个垂直领域有积累,可以卖给同行:

  • 你在做电商价格监控 → 包装成工具卖给其他小电商
  • 你在抓社交媒体数据 → 卖给营销人员

小结

数据采集生意的核心逻辑:

技术壁垒在降低,开源工具(Playwright、Scrapy)让任何人都能写爬虫。真正的壁垒在于:数据的独占性、清洗流程的规模化、以及找到愿意付钱的买家。

最有价值的数据特征:实时性(越新越贵)、唯一性(别人采集不到的)、垂直性(特定行业深度数据)。

入门路径:选一个你熟悉的行业,找到这个行业里有价值的公开数据,用 Scrapy 或 Playwright 采集,在 RapidAPI 发布,定价 $0.01/次调用,看是否有人付费。验证需求后再扩大规模。

下一章,我们进入浏览器指纹和账号矩阵的世界。