4、爬虫与数据采集:Python爬虫基础(Requests/Scrapy)、金融网站API对接、反爬策略与合规注意事项

做金融事件图谱,第一步就是搞数据。没有数据,后面那些实体识别、关系抽取全是空中楼阁。我刚开始做这个项目时,以为最难的是算法模型,后来才发现——把数据稳定、合规地拿回来,才是真正的硬骨头。

这一章,咱们就聊聊数据采集那些事。说白了,就是怎么用Python把金融网站上的信息搬回本地。我会把Requests和Scrapy这两个工具讲透,再聊聊API对接和反爬策略。嗯,合规这块尤其重要,我吃过亏,后面会细说。

4.1 Python爬虫基础:从Requests到Scrapy

我个人习惯,小规模采集用Requests,大规模工程用Scrapy。为什么?你想想看,抓几百条新闻用Requests写个脚本就够了,但要是每天监控上千个金融网站,Scrapy的异步架构能省下你大把时间。

4.1.1 Requests:轻量级爬虫利器

Requests库,说白了就是帮你发HTTP请求的。我见过不少新手用urllib,代码写得又长又丑。其实用Requests,几行代码就搞定。

import requests

# 抓取东方财富网某只股票的新闻
url = "https://finance.eastmoney.com/a/czqyw.html"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
resp = requests.get(url, headers=headers, timeout=10)
print(resp.status_code)  # 200表示成功
print(resp.text[:500])   # 打印前500个字符看看结构

这里有个坑——headers一定要加。我在项目中遇到过,不加User-Agent,很多金融网站直接返回403。你想想看,服务器一看请求里连浏览器标识都没有,肯定怀疑你是爬虫。

小技巧: 我一般用fake_useragent库随机生成User-Agent,每次请求都不一样,能降低被封的概率。

4.1.2 Scrapy:工业级爬虫框架

当你要采集的数据量大了,Requests就有点力不从心了。Scrapy才是正解。它内置了请求调度、去重、管道存储等功能,你只需要写爬虫逻辑就行。

我记得第一次用Scrapy做金融数据采集,目标是抓取沪深两市所有上市公司的公告。如果用Requests,得写几百行代码处理并发和异常。用Scrapy,核心代码不到50行。

import scrapy

class FinanceNewsSpider(scrapy.Spider):
    name = "finance_news"
    start_urls = ["https://finance.eastmoney.com/a/czqyw.html"]

    def parse(self, response):
        # 提取新闻列表
        for news in response.css("div.list-item"):
            yield {
                "title": news.css("a::text").get(),
                "url": news.css("a::attr(href)").get(),
                "time": news.css("span.time::text").get()
            }
        # 翻页
        next_page = response.css("a.next::attr(href)").get()
        if next_page:
            yield scrapy.Request(url=next_page, callback=self.parse)

为什么用Scrapy?异步并发是核心优势。你想想看,Requests是串行的,发一个请求等一个响应。Scrapy基于Twisted异步框架,可以同时发几十个请求,速度能快10倍以上。

实战建议: 做金融事件图谱时,我建议用Scrapy + MongoDB的组合。Scrapy负责采集,MongoDB负责存储非结构化的新闻文本。后面做实体抽取时,直接从MongoDB读数据,效率很高。

4.2 金融网站API对接

爬虫虽然好用,但有些金融数据源提供了官方API。能用API就别用爬虫——这是铁律。为什么?API稳定、合规、数据格式规范,省去了解析HTML的麻烦。

4.2.1 常见金融数据API

数据源 API类型 特点 限制
东方财富 HTTP REST 行情数据丰富,实时性强 有频率限制,需申请token
新浪财经 HTTP REST 免费,接口简单 数据格式不稳定,偶尔变更
Wind Python SDK 数据最全,机构级 收费,年费几万起
Tushare HTTP REST 开源免费,社区活跃 积分制,高级数据需积分

我个人最常用的是Tushare。它提供了A股、港股、基金、期货等各类金融数据,接口设计得很Pythonic。举个例子,获取某只股票的历史行情:

import tushare as ts

# 设置token(在Tushare官网注册获取)
ts.set_token("your_token_here")
pro = ts.pro_api()

# 获取贵州茅台2023年日线数据
df = pro.daily(ts_code="600519.SH", start_date="20230101", end_date="20231231")
print(df.head())
注意: 使用API时,一定要控制请求频率。我曾经因为并发太高,被Tushare封了IP三天。后来学乖了,每次请求之间加个time.sleep(0.5),稳得很。

4.2.2 API对接的通用流程

不管对接哪个金融数据源,流程都差不多:

  1. 注册获取凭证:API Key、Token、App Secret等
  2. 阅读接口文档:搞清楚请求参数、返回格式、频率限制
  3. 编写封装函数:把API调用封装成Python函数,方便复用
  4. 异常处理:网络超时、返回错误码、数据为空等情况都要处理
  5. 数据缓存:避免重复请求,节省API配额

这里我分享一个自己写的API封装模板:

import requests
import time
from functools import lru_cache

class FinanceAPI:
    def __init__(self, token):
        self.token = token
        self.base_url = "https://api.tushare.pro"
        self.last_call_time = 0

    @lru_cache(maxsize=128)
    def get_stock_data(self, code, start, end):
        """获取股票数据,带缓存和频率控制"""
        # 频率控制:每秒最多2次请求
        now = time.time()
        if now - self.last_call_time < 0.5:
            time.sleep(0.5 - (now - self.last_call_time))

        payload = {
            "api_name": "daily",
            "token": self.token,
            "params": {"ts_code": code, "start_date": start, "end_date": end},
            "fields": "trade_date,open,high,low,close,vol"
        }
        resp = requests.post(self.base_url, json=payload)
        self.last_call_time = time.time()

        if resp.status_code == 200:
            data = resp.json()
            if data["code"] != 0:
                raise Exception(f"API错误: {data['msg']}")
            return data["data"]["items"]
        else:
            raise Exception(f"请求失败: {resp.status_code}")

4.3 反爬策略与合规注意事项

这部分很重要,我放在最后说。做金融数据采集,合规是第一位的。我曾经因为爬取某财经网站的新闻数据,被对方法务发了律师函。嗯,从那以后,我对合规格外敏感。

4.3.1 常见的反爬机制

金融网站的反爬手段,说白了就那几招:

  • IP封禁:短时间大量请求,直接封IP
  • User-Agent检测:非浏览器标识的请求被拒绝
  • Cookie验证:需要先访问首页获取Cookie
  • 验证码:触发频率限制后弹出验证码
  • 动态渲染:数据通过JavaScript加载,直接请求拿不到

怎么应对?我总结了几条实战经验:

  • IP代理池:准备一批代理IP,轮换使用。我一般用付费代理,免费的不稳定
  • 请求间隔:随机延迟1-3秒,别搞得太规律
  • 模拟浏览器:用Selenium或Playwright处理动态渲染的页面
  • 分布式爬虫:多台机器、多个IP同时采集,降低单点压力
避坑指南: 我曾经用Scrapy爬某金融网站,并发设了16,结果跑了10分钟IP就被封了。后来改成4并发,每次请求间隔2-5秒随机延迟,稳稳定定跑了三个月没出问题。记住——慢就是快

4.3.2 合规红线

做金融数据采集,有几条红线绝对不能碰:

红线 说明 后果
robots.txt 网站声明禁止爬取的部分 可能被起诉侵权
个人隐私数据 用户手机号、身份证、交易记录等 违反《个人信息保护法》
商业机密 未公开的财报、内幕信息 涉嫌内幕交易
高频请求 对服务器造成过大压力 可能构成破坏计算机信息系统罪

我个人建议,做金融事件图谱时,只采集公开的、合法的数据。比如上市公司公告、财经新闻、行情数据这些。千万别碰用户隐私和未公开信息。

重要提醒: 2021年《数据安全法》实施后,对数据采集的监管更严了。我建议你在项目启动前,找法务同事确认一下数据源的合规性。别等到被约谈了才后悔。

4.4 本章知识体系

说了这么多,我画了一张图帮你梳理本章的核心逻辑。从数据源到存储,每一步都有对应的技术和注意事项。

金融事件图谱数据采集知识体系 金融数据源 采集方式 技术工具 财经网站 金融API 交易所数据 爬虫(Requests/Scrapy) API对接(REST/SDK) 反爬策略 Python + Scrapy 代理IP + 延迟 Selenium/Playwright 合规红线:公开数据 + 频率控制 + 尊重robots.txt 数据存储:MongoDB / MySQL / CSV

这张图把数据采集的流程串起来了。从数据源出发,选择爬虫或API方式,用对应的技术工具实现,同时注意合规和存储。做金融事件图谱,数据采集这一步走稳了,后面的工作才能顺利推进。

专注资料整理