第三章 数据采集基础:网络爬虫原理、Requests库、BeautifulSoup库、API调用基础
各位同学好,我是你们的讲师。今天咱们聊聊数据采集——说白了,就是怎么把互联网上的信息“搬”到我们自己的数据库里。做量化交易也好,做市场情绪分析也罢,没有数据,一切都是空谈。
我个人习惯把数据采集比作“数字世界的淘金”。互联网就是那条奔流不息的金沙江,而爬虫和API,就是我们的淘金工具。嗯,咱们今天就把这两样工具彻底搞明白。
一、网络爬虫的基本原理
网络爬虫,听起来很高大上?其实没那么玄乎。它的核心逻辑就三步:请求 → 响应 → 解析。
- 发送请求:你的程序假装成一个浏览器,向目标服务器说“嘿,把那个网页给我看看”。
- 获取响应:服务器把网页的HTML代码、CSS样式、JavaScript脚本一股脑儿扔回来。
- 解析数据:从这堆乱七八糟的代码里,把我们想要的信息(比如新闻标题、股价、评论情感)提取出来。
我在项目中遇到过不少新手,一上来就想着爬遍全网。其实没必要。你想想看,我们做情绪分析,核心数据源就那么几个——财经新闻、社交媒体、财报公告。把这几条“水源”管好,比什么都强。
核心要点:爬虫不是“偷数据”,而是“礼貌地请求数据”。尊重网站的robots.txt协议,控制请求频率,这是职业操守。
二、Requests库——最顺手的HTTP工具
Python里做网络请求,Requests库绝对是首选。我当年刚入行时还用urllib,那叫一个痛苦。后来换了Requests,感觉整个世界都清爽了。
它的用法极其简单。看个例子:
import requests
# 最基本的GET请求
url = "https://api.example.com/news"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
response = requests.get(url, headers=headers)
# 检查状态码
if response.status_code == 200:
print("请求成功!")
data = response.text # 获取网页源码
else:
print(f"请求失败,状态码:{response.status_code}")
避坑指南:我曾经因为没加User-Agent,被某财经网站封了IP整整一天。记住,很多服务器会检查请求头,没有User-Agent的请求,基本等于在脑门上写着“我是爬虫”。
对于需要登录的网站,Requests也能处理。用Session对象保持会话,加上Cookie或Token就行:
session = requests.Session()
login_data = {"username": "your_account", "password": "your_password"}
session.post("https://example.com/login", data=login_data)
# 之后的所有请求都会自动携带登录信息
response = session.get("https://example.com/dashboard")
三、BeautifulSoup——HTML解析利器
拿到网页源码后,怎么把数据“掏”出来?BeautifulSoup就是干这个的。它能把杂乱的HTML变成一棵清晰的树,然后我们用选择器去摘叶子。
我个人习惯用lxml作为解析器,速度比Python内置的html.parser快不少。安装时记得:pip install beautifulsoup4 lxml
from bs4 import BeautifulSoup
html = """
<div class="news-list">
<div class="item">
<h2>股市大涨,情绪指数飙升</h2>
<span class="date">2025-03-15</span>
</div>
<div class="item">
<h2>美联储加息预期升温</h2>
<span class="date">2025-03-14</span>
</div>
</div>
"""
soup = BeautifulSoup(html, "lxml")
# 提取所有新闻标题
titles = soup.select(".item h2")
for title in titles:
print(title.get_text(strip=True))
# 提取日期
dates = soup.select(".item .date")
for date in dates:
print(date.get_text(strip=True))
实战经验:用select()方法配合CSS选择器,比find_all()更直观。你想想看,写CSS选择器就像在给网页元素“点名”,谁该出来谁就出来。
四、API调用——更优雅的数据获取方式
爬虫虽好,但有个硬伤——网站改版你就得跟着改代码。API就不同了,它是官方提供的“数据水龙头”,稳定、规范、有文档。
做量化交易,很多数据源都提供API。比如新浪财经的免费接口、Alpha Vantage、甚至一些区块链数据平台。调用方式大同小异:
import requests
import json
# 以某财经API为例
api_url = "https://api.xxx.com/v1/market/sentiment"
params = {
"symbol": "AAPL",
"apikey": "your_api_key_here",
"outputsize": "compact"
}
response = requests.get(api_url, params=params)
if response.status_code == 200:
data = response.json() # 直接解析JSON
print(f"当前情绪得分:{data['sentiment_score']}")
else:
print("API调用失败")
注意:API调用通常有频率限制(Rate Limit)。我曾经在测试时忘了加延时,结果一分钟内调了200次,直接被封号三天。建议每次请求后至少sleep(1),或者用time.sleep()控制节奏。
五、数据采集的“避坑”清单
做数据采集这几年,我踩过的坑比走过的路还多。总结几条血泪教训:
- 反爬虫机制:别以为加个User-Agent就万事大吉。有些网站会检测请求间隔、浏览器指纹、甚至JavaScript执行环境。遇到这种情况,可以考虑用Selenium模拟真实浏览器。
- 数据编码问题:中文网站经常用GBK或GB2312编码。Requests获取的
response.text默认用UTF-8解码,遇到乱码时记得指定编码:response.encoding = 'gbk'。 - 异常处理:网络请求没有100%成功的。一定要加try-except,捕获
requests.exceptions.RequestException。我曾经因为没处理超时异常,整个爬虫在半夜挂掉,第二天才发现数据是空的。 - 数据存储:爬下来的数据别直接扔内存里。建议边爬边存,用CSV或SQLite都行。万一程序崩溃,至少前面的数据还在。
六、实战:抓取一条新闻标题
光说不练假把式。咱们来一个完整的例子:从某个新闻网站抓取头条标题。
import requests
from bs4 import BeautifulSoup
import time
def fetch_headlines(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
try:
resp = requests.get(url, headers=headers, timeout=10)
resp.raise_for_status() # 自动抛出HTTP错误
except requests.exceptions.RequestException as e:
print(f"请求失败:{e}")
return []
soup = BeautifulSoup(resp.text, "lxml")
headlines = []
# 假设新闻标题都在 h3 标签下的 a 链接里
for item in soup.select("h3 a"):
title = item.get_text(strip=True)
if title:
headlines.append(title)
return headlines
# 使用示例
url = "https://finance.example.com"
result = fetch_headlines(url)
for i, title in enumerate(result[:5], 1):
print(f"{i}. {title}")
time.sleep(0.5) # 礼貌性延时
小技巧:调试时先用print(resp.text[:500])看看返回的HTML结构,确认选择器写对了再批量提取。这能省下大量调试时间。
好了,数据采集的基础就讲到这里。记住,爬虫和API只是工具,真正重要的是你如何理解数据、清洗数据、最终用它来驱动你的交易策略。下一章我们会深入数据清洗和预处理,那才是真正考验功力的地方。
公众号:蓝海资料掘金营,微信deep3321