第三章 Python数据采集基础
数据采集,说白了就是给量化模型找吃的。没有数据,再牛的因子也是空中楼阁。这一章我们聊聊怎么把REITs市场的数据从网上拽下来,存到本地。
我个人习惯把数据采集分成三层:静态页面、动态页面、反爬对抗。咱们一层层剥开。
3.1 requests库:最基础的HTTP工具
requests库是Python里最常用的HTTP请求库。它的用法极其简单,我刚开始做数据采集时,第一个接触的就是它。
核心用法:
import requests
# 最简单的GET请求
url = "https://api.reitsdata.com/daily"
response = requests.get(url)
# 检查状态码
if response.status_code == 200:
data = response.json() # 如果是JSON格式
print(data)
else:
print(f"请求失败,状态码:{response.status_code}")
嗯,这里要注意:很多REITs数据网站会检查请求头。我遇到过好几次,明明URL是对的,但返回空数据。后来发现是缺少User-Agent。
避坑指南:我曾经因为没加请求头,被一个REITs数据源封了IP三天。后来养成了习惯,每次请求都带上浏览器伪装。
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept": "application/json"
}
response = requests.get(url, headers=headers)
你想想看,如果连请求头都不伪装,服务器一看就知道你是爬虫。所以,headers是基本功。
3.2 BeautifulSoup解析:从HTML里挖数据
拿到HTML页面后,怎么提取我们需要的数据?BeautifulSoup就是干这个的。它能把HTML变成一棵树,我们按标签、类名、ID去摘叶子。
解析流程:
from bs4 import BeautifulSoup
import requests
url = "https://reits.example.com/list"
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
# 找到所有REITs代码
reit_codes = soup.find_all('span', class_='reit-code')
for code in reit_codes:
print(code.text.strip())
我个人习惯用lxml作为解析器,速度比html.parser快不少。安装时记得pip install lxml。
注意:有些网站会动态加载数据,BeautifulSoup只能解析静态HTML。如果发现页面内容不全,那就要上Selenium了。
3.3 Selenium动态页面抓取
REITs的实时行情、K线图、分红日历,很多都是JavaScript动态渲染的。这时候requests+BeautifulSoup就抓瞎了。Selenium可以模拟真实浏览器,等JS执行完再抓数据。
基本用法:
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
# 启动浏览器
driver = webdriver.Chrome() # 需要安装ChromeDriver
driver.get("https://reits.example.com/dashboard")
# 等待页面加载
time.sleep(3) # 简单等待,实际项目用WebDriverWait
# 获取动态内容
price_element = driver.find_element(By.CLASS_NAME, "current-price")
print(f"当前价格:{price_element.text}")
driver.quit()
我记得有一次抓取REITs的分红数据,页面要滚动才能加载更多。Selenium可以模拟滚动,这个很实用。
技巧:用driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")模拟滚动加载。
为什么不用Selenium干所有事?因为它慢。每个请求都要启动浏览器,加载CSS、图片、JS。所以我的原则是:能用requests解决的,绝不用Selenium。
3.4 反爬策略应对
做数据采集,反爬是绕不开的坎。REITs数据源虽然不像电商那么严防死守,但该有的反爬措施一样不少。
| 反爬手段 | 常见表现 | 应对策略 |
|---|---|---|
| IP封禁 | 请求返回403 | 使用代理IP池 |
| 请求频率限制 | 返回429状态码 | 添加随机延时 |
| 验证码 | 弹出图片验证 | 使用打码平台或OCR |
| User-Agent检测 | 返回空数据 | 随机切换UA |
| Cookie验证 | 需要登录态 | 模拟登录或使用Session |
重要提醒:我曾经因为爬取频率太高,被一个REITs数据源永久封禁了账号。后来学乖了,每次请求之间至少间隔1-3秒,并且随机化。
实战中,我常用的反爬应对代码片段:
import time
import random
from fake_useragent import UserAgent
ua = UserAgent()
def safe_request(url, max_retries=3):
for i in range(max_retries):
try:
headers = {"User-Agent": ua.random}
time.sleep(random.uniform(1, 3)) # 随机延时
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
return response
elif response.status_code == 429:
print("触发频率限制,等待更久...")
time.sleep(60)
else:
print(f"状态码异常:{response.status_code}")
except Exception as e:
print(f"请求失败:{e}")
time.sleep(5)
return None
你想想看,如果每个请求都一模一样,服务器很容易识别出你是爬虫。所以随机化是关键。
3.5 本章知识体系
下面这张图,是我梳理的数据采集核心流程。建议你保存下来,做项目时对照着看。
这张图把整个数据采集流程串起来了。从数据源出发,先判断页面是静态还是动态,然后选择对应的工具,最后经过反爬对抗,输出结构化数据。
我的经验:实际项目中,80%的REITs数据可以用requests+BeautifulSoup搞定。只有那些需要登录、滚动加载、实时刷新的页面,才值得上Selenium。别一上来就上重武器。
好了,这一章就到这里。数据采集是量化研究的地基,地基不牢,后面全白搭。下一章我们聊聊数据清洗,那又是另一番风景。