在需要把多个网页中的表格、商品列表或文章正文一次性保存下来时,靠浏览器手动另存为效率极低。通过编写采集脚本,我们可以让程序自动请求页面、提取HTML中的目标数据并批量写入本地文件,从而实现稳定的HTML数据批量下载。

一、明确采集目标与页面结构
动手写代码前,首先要分析目标站点的HTML结构。打开浏览器开发者工具,查看包含数据的标签路径。例如某列表页中,每一条数据都在<li class="item">内部,标题在<h3>,价格在一个带有特定类的<span>中。只有把选择器找准,后续解析才不会漏抓或误抓。
另外要注意页面是静态HTML还是通过接口动态渲染。如果是静态页面,直接获取HTML源码就能解析;如果数据由JavaScript异步加载,就需要使用能执行JS的环境,否则只能从网络面板里找到真实的数据接口地址。
二、基于Python的静态页面批量下载方案
对于静态HTML,最基础的自动化方案是使用requests库发送HTTP请求,再用BeautifulSoup解析。下面示例展示如何遍历三页列表并提取标题与价格,最后保存为CSV文件。
import requests
from bs4 import BeautifulSoup
import csv
headers = {'User-Agent': 'Mozilla/5.0'}
all_data = []
for page in range(1, 4):
url = f'https://ipipp.com/list?page={page}'
resp = requests.get(url, headers=headers, timeout=10)
soup = BeautifulSoup(resp.text, 'html.parser')
for li in soup.select('li.item'):
title = li.find('h3').get_text(strip=True)
price = li.select_one('span.price').get_text(strip=True)
all_data.append({'title': title, 'price': price})
with open('result.csv', 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.DictWriter(f, fieldnames=['title', 'price'])
writer.writeheader()
writer.writerows(all_data)
上述代码通过循环构造分页URL,使用select方法匹配<li class="item">节点,再用find与select_one获取子元素文本。写入CSV时指定utf-8-sig编码,可避免Excel打开中文乱码。
这种方案优点是实现简单、依赖少、速度快;缺点是无法处理需要登录态或JS渲染的页面。若目标站有反爬机制,还需在headers中补充Referer、Cookie,并加入time.sleep控制请求间隔。
三、动态渲染页面的无头浏览器方案
当数据由前端框架异步填充时,requests拿到的HTML往往不含目标节点。此时可用Playwright或Selenium启动无头浏览器,等待页面执行完脚本后再读取DOM。
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto('https://ipipp.com/dynamic', wait_until='networkidle')
items = page.query_selector_all('li.item')
for item in items:
print(item.inner_text())
browser.close()
无头浏览器会完整加载页面资源,因此能拿到和真实用户看到一致的内容。query_selector_all等价于CSS选择器批量选取,inner_text可获取渲染后的文本。
该方式胜在通用性强,几乎能采集任何网站;但资源占用高、单页耗时更长。在批量任务中建议配合并发控制,或优先寻找背后JSON接口以降低开销。
四、请求频率与异常处理要点
批量下载本质是高频率访问,必须做好异常处理与限速。建议用try except包裹单次请求,失败重试不超过三次,并使用随机短延时模拟人工节奏。
import time
import random
def safe_get(url, headers):
for i in range(3):
try:
r = requests.get(url, headers=headers, timeout=8)
if r.status_code == 200:
return r.text
except Exception as e:
print('retry', e)
time.sleep(random.uniform(1, 3))
return None
通过safe_get函数,我们把网络波动和临时封禁带来的影响降到最低。随机延时让访问模式不呈现严格周期,减少触发风控的概率。
此外,批量任务应记录日志,标记哪些页成功、哪些页失败,方便断点续跑。将已采集的URL存入集合,重启脚本时跳过,可避免重复下载浪费带宽。
五、数据落盘与格式选择
提取出的HTML数据可以保存为CSV、JSON或直接进入数据库。如果后续要用Excel分析,CSV最方便;若数据结构嵌套深,JSON更合适;长期采集则建议写进SQLite或MySQL。
| 格式 | 适用场景 | 优点 |
|---|---|---|
| CSV | 扁平表格 | 易被表格软件打开 |
| JSON | 层级数据 | 保留结构关系 |
| 数据库 | 持续累积 | 支持查询去重 |
无论选哪种,都应在写入前对字段做清洗,比如去除空白符、统一日期格式。这样下游系统读取时不必再处理脏数据,整体流水线更健壮。
综合来看,HTML数据批量下载并不复杂,核心是先看透页面结构,再选静态解析或无头浏览器,最后用合理的限速与存储策略把自动化方案稳定运行起来。