这个代码是一个用于爬取国家统计局网站数据的Python脚本。下面我将详细解释代码的各个部分及其设计思路。
代码结构概述
import requests # 发送HTTP请求
from bs4 import BeautifulSoup # 解析HTML
import pandas as pd # 数据处理和存储
import time # 时间控制
import random # 随机数生成
import os # 文件系统操作
import re # 正则表达式
函数设计思路
1. 请求头设置
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp...',
'referer': 'https://www.stats.gov.cn/sj/zxfbhjd/202508/t20250822_1960866.html'
}
设计思路:
模拟真实浏览器行为,避免被网站反爬机制拦截
设置Referer头,使请求看起来是从合法页面跳转而来
使用常见的User-Agent字符串,增加请求的合法性
2. 随机延迟机制
time.sleep(random.uniform(1, 3))
设计思路:
避免过于频繁的请求导致IP被封
使用随机时间间隔,模拟人类操作的不规律性
1-3秒的间隔既不会太慢影响效率,也不会太快触发反爬
3. 请求与响应处理
response = requests.get(url, headers=headers, timeout=30)
response.encoding = 'utf-8' # 设置编码
设计思路:
设置30秒超时,避免长时间等待无响应
显式设置编码为UTF-8,确保中文正确显示
检查状态码,确保请求成功
4. 表格解析与处理
tables = soup.find_all('table')
# 分析表格结构
max_cols = 0
for j, row in enumerate(rows):
cells = row.find_all(['td', 'th'])
if len(cells) > max_cols:
max_cols = len(cells)
设计思路:
查找页面中的所有表格
分析每个表格的结构,确定最大列数
确保每行数据有相同的列数,避免DataFrame创建时出错
代码解析
1. tables = soup.find_all('table')
作用:查找HTML文档中的所有
<table>
元素设计思路:国家统计局的数据通常以表格形式展示,所以首先找到所有表格
2. cells = row.find_all(['td', 'th'])
作用:在每一行中查找所有的
<td>
(表格数据单元格)和<th>
(表格标题单元格)元素为什么同时查找td和th:
<td>
是普通数据单元格<th>
是表头单元格,通常包含列标题两者都需要提取,因为表头也包含重要信息
有些表格可能混合使用td和th,或者使用th作为行标题
3. if len(cells) > max_cols: max_cols = len(cells)
作用:确定表格的最大列数
为什么需要这个:
HTML表格可能有不规则结构(某些行可能有合并的单元格)
为了创建规整的DataFrame,需要知道表格的最大宽度
确保所有行都有相同的列数,不足的用空值填充
设计思路详解
1. 处理不规则表格
HTML表格可能有不规则结构,例如:
<table>
<tr>
<th>标题1</th>
<th>标题2</th>
<th>标题3</th>
</tr>
<tr>
<td>数据1</td>
<td colspan="2">合并单元格</td> <!-- 这一行只有2个单元格,但占据2列 -->
</tr>
</table>
在这种情况下,代码会:
第一行:找到3个单元格(th),设置max_cols=3
第二行:找到2个单元格(td),但max_cols保持3
后续处理时,第二行会被填充到3列(添加一个空单元格)
2. 确保数据规整性
通过确定最大列数,可以:
创建统一结构的DataFrame
避免因列数不一致导致的数据错位
保持数据的完整性,便于后续分析
3. 完整的工作流程
这段代码是完整表格处理流程的一部分:
找到所有表格
对每个表格,确定最大列数
逐行处理,确保每行有相同的列数
创建规整的二维数组
转换为DataFrame进行后续处理
<