第三章:数据采集实战——API调用、Web Scraping与数据购买交换
数据采集这事儿,说白了就是“找米下锅”。
我做了这么多年数据分析,最深的体会是:数据质量决定分析上限。你算法再牛,模型再炫,喂进去的是垃圾,出来的还是垃圾。这一章,咱们就聊聊怎么把“米”搞到手——API调用、爬虫、还有数据购买与交换协议。
核心观点:数据采集不是简单的“复制粘贴”,而是一场与数据源斗智斗勇的博弈。你需要懂技术、懂法律、懂商业。
3.1 API调用:最优雅的数据获取方式
API,全称是应用程序接口。我个人习惯把它理解成“数据餐厅的菜单”——你点菜(传参),厨房做菜(服务器处理),服务员端上来(返回数据)。
为什么说它优雅?因为API是数据源方主动提供的、结构化的、有文档的接口。你不需要去猜数据长什么样,也不用担心对方改页面结构。
3.1.1 RESTful API 调用实战
目前最主流的API风格是RESTful。我拿一个真实案例来说——调用某金融数据平台的股票行情API。
import requests
import json
# 配置参数
api_key = "your_api_key_here"
symbol = "AAPL"
endpoint = f"https://api.financedata.com/v1/quote/{symbol}"
# 设置请求头
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
# 发送GET请求
response = requests.get(endpoint, headers=headers)
# 检查状态码
if response.status_code == 200:
data = response.json()
print(f"当前价格: {data['price']}")
print(f"涨跌幅: {data['change_percent']}%")
else:
print(f"请求失败,状态码: {response.status_code}")
嗯,这里要注意几个坑:
- API Key 别硬编码——我见过有人把key直接写在代码里然后传到GitHub上,第二天就被盗刷了。用环境变量或者配置文件。
- 限流(Rate Limiting)——大部分API都有调用次数限制。我曾经在项目中没注意这个,结果爬到一半被封了IP,整个项目延期两天。
- 错误处理——网络请求一定会失败,别假设它永远成功。
小技巧:用 time.sleep() 控制请求频率,或者用 retry 库实现自动重试。我一般设置每次请求间隔0.5-1秒,既不会触发限流,也不会太慢。
3.1.2 认证方式:从Basic到OAuth 2.0
| 认证方式 | 适用场景 | 安全性 | 我的建议 |
|---|---|---|---|
| API Key | 简单数据查询 | 低 | 仅用于测试或低敏感数据 |
| Basic Auth | 内部系统 | 中 | 配合HTTPS使用 |
| OAuth 2.0 | 开放平台、第三方登录 | 高 | 生产环境首选 |
| JWT | 微服务间通信 | 高 | 适合无状态场景 |
你想想看,如果数据涉及用户隐私或者交易信息,千万别偷懒用API Key。OAuth 2.0虽然配置麻烦点,但安全多了。
3.2 Web Scraping:当API不存在时
现实很骨感——很多有价值的数据根本没有API。比如某些行业报告网站、论坛帖子、电商评论。这时候就得靠爬虫了。
但我要先说一句:爬虫有法律风险。我曾经接过一个项目,客户要求爬取某竞品网站的全部产品数据。我查了一下对方的robots.txt,明确写了“Disallow: /”,而且网站有版权声明。我直接拒绝了——这活儿不能干。
避坑指南:爬虫前一定要看三样东西——robots.txt、网站服务条款、当地数据保护法规。我曾经有个同事没注意这些,结果被对方发了律师函,公司赔了20万和解。
3.2.1 静态页面爬取:BeautifulSoup + Requests
对于简单的静态页面,这两个库就够了。我拿爬取某新闻网站标题举例:
from bs4 import BeautifulSoup
import requests
url = "https://news.example.com/tech"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# 找到所有文章标题
titles = soup.find_all('h2', class_='article-title')
for title in titles:
print(title.get_text().strip())
这里有个坑——很多网站会动态加载内容。你直接用requests拿到的HTML可能是空的,因为数据是通过JavaScript异步加载的。这时候就需要Selenium了。
3.2.2 动态页面爬取:Selenium + Chrome Driver
Selenium能模拟真实浏览器行为,包括执行JavaScript、点击按钮、滚动页面。
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
# 启动浏览器
driver = webdriver.Chrome()
driver.get("https://news.example.com/tech")
# 等待页面加载
time.sleep(3)
# 滚动到底部加载更多内容
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)
# 获取所有标题
titles = driver.find_elements(By.CSS_SELECTOR, "h2.article-title")
for title in titles:
print(title.text)
说实话,Selenium很慢,而且容易暴露。我一般只在不得已时才用它。更好的方案是分析网站的XHR请求,直接模拟API调用——这需要你打开浏览器的开发者工具,看Network面板。
进阶技巧:很多网站的数据是通过GraphQL接口返回的。你可以在Network里找到对应的请求,复制cURL命令,然后用Python的requests库模拟。这样既快又不容易被封。
3.3 数据购买与交换协议
有些数据,你既调不到API,也爬不到——比如交易所的实时行情、医疗机构的病例数据、运营商的信令数据。这些数据要么太敏感,要么太值钱,只能通过商业渠道获取。
3.3.1 数据购买:从定价到交付
数据购买不是简单的“一手交钱一手交货”。我参与过几次数据采购,总结下来有几个关键点:
- 数据样本先行——别急着付全款。先让对方提供1%的样本数据,验证质量和格式。我见过有人买了整份数据后发现字段全是空的,钱打了水漂。
- 交付格式要明确——CSV、JSON、Parquet?压缩方式?分片规则?这些都要写进合同。
- 更新频率——是买断历史数据,还是包含定期更新?如果是后者,更新周期是多久?
| 数据类型 | 常见定价模式 | 我的经验 |
|---|---|---|
| 金融行情数据 | 按订阅(月/年) | 注意延迟等级,Level 1和Level 2价格差10倍 |
| 社交媒体数据 | 按API调用次数 | 量大的话谈包年套餐 |
| 行业报告 | 按份购买 | 注意版权限制,能否二次分发 |
| 地理位置数据 | 按数据量(GB/TB) | 确认数据脱敏程度 |
3.3.2 数据交换协议:双赢还是陷阱?
数据交换,说白了就是“我用我的数据换你的数据”。听起来很美好,但实际操作中坑很多。
我记得有一次,一家电商平台想用他们的用户画像数据,换一家支付公司的交易流水数据。双方谈了很久,最后卡在了一个问题上:数据怎么脱敏?
电商平台说“我们把用户ID哈希一下就行”,支付公司说“哈希也能被彩虹表破解”。最后双方各退一步,用了差分隐私技术,加了一定程度的噪声。
数据交换协议的核心要素:
- 数据范围——明确交换哪些字段,哪些不能交换
- 脱敏标准——K-匿名、L-多样性、差分隐私,选哪种?
- 使用限制——数据只能用于什么场景?能不能转售?
- 审计机制——怎么确保对方没有滥用数据?
- 退出条款——合作终止后,数据怎么处理?
3.4 本章知识体系总览
说了这么多,我画了一张图帮你理清思路。三种数据获取方式各有优劣,关键是根据场景选对工具。
好了,这一章的内容就到这里。数据采集是数据分析的基石,但也是最容易出问题的环节。我个人建议:能用API就别爬,能买就别偷,能合作就别单干。下一章咱们聊聊数据清洗——你会发现,拿到数据只是开始,真正的麻烦还在后头。