第3章:数据采集基础:Python爬虫入门(requests + BeautifulSoup)

做量化分析,数据就是命根子。

我见过太多人,策略模型写得天花乱坠,结果一跑起来,数据源断了,或者拿到的数据全是错的。说白了,没有靠谱的数据采集,后面的一切都是空中楼阁。

这一章,我们就来搞定最基础、也是最核心的一环——用Python爬虫抓取财经新闻标题和评论数据。别怕,没那么玄乎,跟着我一步步来。

3.1 为什么非得自己爬数据?

你可能会问:现在不是有很多现成的数据API吗?

嗯,确实有。但现实是:

  • 收费贵:专业金融数据接口,一年几万到几十万不等,个人玩家根本扛不住。
  • 有延迟:免费API往往有15分钟甚至更长的延迟,做短线分析基本废了。
  • 数据不全:很多平台只提供结构化数据,但新闻标题、评论这种非结构化数据,它们不给你。

所以,自己动手爬,是最灵活、最省钱的方式。我在做舆情因子研究时,就靠这个抓了上百万条新闻标题,效果出奇的好。

3.2 准备工作:装好你的工具箱

我们需要两个核心库:

  • requests:用来发HTTP请求,说白了就是模拟浏览器去访问网页。
  • BeautifulSoup:用来解析HTML,从一堆标签里把我们需要的数据提取出来。

安装很简单,一行命令搞定:

pip install requests beautifulsoup4
小提示: 我个人习惯在虚拟环境里装,避免跟其他项目冲突。你如果刚入门,直接装全局也行,问题不大。

3.3 第一个实战:抓取财经新闻标题

我们拿东方财富网的新闻板块来练手。为什么选它?因为结构相对规整,适合新手。

先看代码:

import requests
from bs4 import BeautifulSoup

# 目标网址
url = 'https://finance.eastmoney.com/a/czqyw.html'

# 伪装成浏览器,别让服务器认出你是爬虫
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}

# 发请求
response = requests.get(url, headers=headers)
response.encoding = 'utf-8'

# 解析HTML
soup = BeautifulSoup(response.text, 'html.parser')

# 找到新闻标题所在的标签
# 我观察过,东方财富的新闻标题都在 <a> 标签里,class 为 'title'
news_items = soup.find_all('a', class_='title')

for item in news_items[:10]:  # 先打印前10条
    title = item.get_text(strip=True)
    link = item.get('href')
    print(f'标题:{title}')
    print(f'链接:{link}')
    print('---')

跑一下,你就能看到类似这样的输出:

标题:A股三大指数震荡整理 半导体板块走强
链接:https://finance.eastmoney.com/a/202503213456789.html
---
标题:央行最新表态:货币政策仍有空间
链接:https://finance.eastmoney.com/a/202503213456790.html
---
核心要点:
  • User-Agent一定要加,不加的话很多网站直接拒绝你。我曾经因为忘了加这个,排查了半天,结果就是被反爬了。
  • 编码设置:response.encoding = 'utf-8',不然中文会乱码。
  • find_all的用法:第一个参数是标签名,第二个参数是筛选条件。class_后面有个下划线,因为class是Python关键字。

3.4 进阶:抓取评论数据

新闻标题好抓,评论就麻烦一点。很多网站的评论是动态加载的,直接抓HTML拿不到。

怎么办?

我常用的方法是:打开浏览器的开发者工具(F12),看Network面板,找到真正的数据接口。

以某财经网站为例,评论数据通常是通过AJAX请求加载的,返回的是JSON格式。我们直接模拟这个请求就行:

import requests
import json

# 评论数据的真实接口(从浏览器里找到的)
comment_url = 'https://comment.eastmoney.com/api/comment/list'

params = {
    'article_id': '123456789',  # 新闻的ID
    'page': 1,
    'page_size': 20
}

headers = {
    'User-Agent': 'Mozilla/5.0',
    'Referer': 'https://finance.eastmoney.com/'  # 有些网站会检查来源
}

resp = requests.get(comment_url, params=params, headers=headers)
data = resp.json()

# 提取评论内容
for comment in data['data']['list']:
    content = comment['content']
    print(f'评论:{content}')
避坑指南:
  • 频率控制:别一秒发几十个请求,会被封IP。我一般加个time.sleep(1)。
  • Referer检查:有些网站会验证请求来源,不加Referer直接返回空数据。我曾经在这上面栽过跟头。
  • 数据格式:返回的JSON结构每个网站都不一样,需要耐心解析。建议先用print(data)看看整体结构。

3.5 本章知识体系

下面这张图,帮你把整个流程串起来:

数据采集核心流程 1. 分析目标网站 2. 发送HTTP请求 3. 解析响应数据 响应格式判断 HTML → BeautifulSoup解析 JSON → 直接提取字段 输出:结构化数据 分析 请求 解析 输出

3.6 避坑总结

最后,分享几个我踩过的坑:

  • 别用默认的User-Agent:很多网站直接屏蔽Python的默认请求头。我一般从浏览器里复制一个真实的User-Agent过来。
  • 注意请求频率:我曾经为了赶项目,写了个循环每秒发10个请求,结果IP被封了三天。后来学乖了,每次请求之间至少等1秒。
  • 数据清洗不能省:爬下来的数据经常带空格、换行、HTML标签。记得用strip()和正则表达式清理一下。
  • 保存原始数据:我习惯把爬到的原始HTML或JSON先存一份,万一解析逻辑写错了,还能重新来过。

嗯,这一章的内容就到这。代码不多,但都是实战经验。你照着敲一遍,基本就能上手了。


蓝海数据掘金营,专注资料整理