第三章 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 本章知识体系

下面这张图,是我梳理的数据采集核心流程。建议你保存下来,做项目时对照着看。

REITs数据采集核心流程 REITs数据源 页面类型? requests + BeautifulSoup Selenium动态抓取 反爬对抗:IP代理、UA伪装、延时 结构化数据输出

这张图把整个数据采集流程串起来了。从数据源出发,先判断页面是静态还是动态,然后选择对应的工具,最后经过反爬对抗,输出结构化数据。

我的经验:实际项目中,80%的REITs数据可以用requests+BeautifulSoup搞定。只有那些需要登录、滚动加载、实时刷新的页面,才值得上Selenium。别一上来就上重武器。

好了,这一章就到这里。数据采集是量化研究的地基,地基不牢,后面全白搭。下一章我们聊聊数据清洗,那又是另一番风景。


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