本文目录导读:

- Python + BeautifulSoup(静态网页)
- Python + Pandas(快速方法)
- Selenium(动态网页)
- 处理分页表格
- 错误处理和重试机制
- 保存数据到Excel
- 完整示例:综合脚本
- 注意事项
- 常见问题解决
Python + BeautifulSoup(静态网页)
基础示例
import requests
from bs4 import BeautifulSoup
import pandas as pd
# 发送请求
url = 'https://example.com/table'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.get(url, headers=headers)
response.encoding = 'utf-8'
# 解析HTML
soup = BeautifulSoup(response.text, 'html.parser')
# 找到表格
table = soup.find('table') # 或 soup.find_all('table')
# 提取数据
data = []
for row in table.find_all('tr'):
row_data = []
for cell in row.find_all(['td', 'th']):
row_data.append(cell.text.strip())
if row_data:
data.append(row_data)
# 转换为DataFrame
df = pd.DataFrame(data)
更高级的表格处理
def extract_table_data(soup, table_index=0):
"""提取表格数据的通用函数"""
tables = soup.find_all('table')
if table_index >= len(tables):
return None
table = tables[table_index]
rows = table.find_all('tr')
headers = []
data = []
# 提取表头
header_row = rows[0]
headers = [th.text.strip() for th in header_row.find_all(['th', 'td'])]
# 提取数据行
for row in rows[1:]:
row_data = []
for cell in row.find_all(['td', 'th']):
# 处理 colspan 和 rowspan
rowspan = int(cell.get('rowspan', 1))
colspan = int(cell.get('colspan', 1))
cell_text = cell.text.strip()
# 复制单元格以处理跨行跨列
for i in range(colspan):
row_data.append(cell_text)
if row_data:
data.append(row_data)
# 处理不完整的行(补齐空值)
max_length = max(len(row) for row in data) if data else 0
for row in data:
while len(row) < max_length:
row.append('')
return headers, data
Python + Pandas(快速方法)
最简单的表格提取
import pandas as pd
# 方法1:直接从网页读取所有表格
tables = pd.read_html('https://example.com/page')
df = tables[0] # 第一个表格
# 方法2:指定表格
df = pd.read_html(url, match='表格名称')[0]
# 方法3:带header参数
df = pd.read_html(url, header=0)[0]
# 方法4:处理多个表格
for i, table in enumerate(tables):
print(f"表格{i}: {table.shape}")
table.to_csv(f'table_{i}.csv', index=False)
Selenium(动态网页)
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pandas as pd
import time
def scrape_dynamic_table():
# 初始化驱动
driver = webdriver.Chrome()
driver.get('https://example.com/dynamic-table')
# 等待表格加载(等待指定元素出现)
wait = WebDriverWait(driver, 10)
table = wait.until(EC.presence_of_element_located((By.TAG_NAME, 'table')))
# 滚动加载更多数据的场景
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(2)
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
# 提取表格数据
rows = driver.find_elements(By.CSS_SELECTOR, 'table tbody tr')
data = []
for row in rows:
cols = row.find_elements(By.TAG_NAME, 'td')
row_data = [col.text.strip() for col in cols]
data.append(row_data)
# 提取表头
headers = [th.text.strip() for th in driver.find_elements(By.CSS_SELECTOR, 'table thead th')]
df = pd.DataFrame(data, columns=headers)
driver.quit()
return df
处理分页表格
def scrape_paginated_table(base_url, total_pages=10):
all_data = []
for page in range(1, total_pages + 1):
# 构建分页URL
url = f"{base_url}?page={page}"
# 使用requests或selenium获取页面
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# 提取当前页数据
table_data = extract_table_data(soup)
if table_data:
headers, data = table_data
all_data.extend(data)
# 暂停避免过快请求
time.sleep(1)
return pd.DataFrame(all_data, columns=headers)
错误处理和重试机制
import time
from functools import wraps
def retry(max_attempts=3, delay=1):
"""重试装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise e
time.sleep(delay * (attempt + 1))
return None
return wrapper
return decorator
@retry(max_attempts=3, delay=2)
def scrape_data_safely(url):
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,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Connection': 'keep-alive',
}
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
return response.text
保存数据到Excel
def save_to_excel(df, filename, sheet_name='Sheet1'):
"""保存数据到Excel"""
with pd.ExcelWriter(filename, engine='openpyxl', mode='w') as writer:
df.to_excel(writer, sheet_name=sheet_name, index=False)
# 调整列宽
worksheet = writer.sheets[sheet_name]
for column in df:
column_width = max(df[column].astype(str).map(len).max(), len(column))
col_idx = df.columns.get_loc(column)
worksheet.column_dimensions[chr(65 + col_idx)].width = column_width + 2
print(f"数据已保存到 {filename}")
# 使用示例
save_to_excel(df, 'output.xlsx', '数据表')
完整示例:综合脚本
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import os
class TableScraper:
def __init__(self, base_url, headers=None):
self.base_url = base_url
self.headers = headers or {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8'
}
self.data = []
self.headers_list = []
def fetch_page(self, url):
"""获取页面内容"""
try:
response = requests.get(url, headers=self.headers, timeout=10)
response.raise_for_status()
response.encoding = 'utf-8'
return response.text
except Exception as e:
print(f"请求失败: {e}")
return None
def extract_tables(self, html):
"""从HTML中提取表格"""
soup = BeautifulSoup(html, 'html.parser')
tables = soup.find_all('table')
results = []
for table in tables:
# 提取表格标题(如果有)
caption = table.find('caption')
caption_text = caption.text.strip() if caption else "无标题"
# 提取表头和数据
headers, data = self.parse_table(table)
results.append({
'caption': caption_text,
'headers': headers,
'data': data
})
return results
def parse_table(self, table):
"""解析单个表格"""
rows = table.find_all('tr')
headers = []
data = []
# 处理表头
header_row = rows[0] if rows else None
if header_row:
headers = [th.text.strip() for th in header_row.find_all(['th', 'td'])]
# 处理数据行
for row in rows[1:]:
row_data = []
for cell in row.find_all(['td', 'th']):
row_data.append(cell.text.strip())
# 验证行长度
if len(row_data) == len(headers):
data.append(row_data)
elif len(row_data) > len(headers):
data.append(row_data[:len(headers)])
elif len(row_data) < len(headers):
# 补齐缺失数据
row_data.extend([''] * (len(headers) - len(row_data)))
data.append(row_data)
return headers, data
def save_to_file(self, format_type='csv', filename='output'):
"""保存数据"""
if not self.data:
print("没有数据可保存")
return
if format_type == 'csv':
self.save_csv(filename)
elif format_type == 'excel':
self.save_excel(filename)
elif format_type == 'json':
self.save_json(filename)
def save_csv(self, filename):
"""保存为CSV"""
os.makedirs(filename, exist_ok=True)
for i, (headers, data) in enumerate(zip(self.headers_list, self.data)):
df = pd.DataFrame(data, columns=headers)
df.to_csv(f"{filename}/table_{i+1}.csv", index=False, encoding='utf-8-sig')
def save_excel(self, filename):
"""保存为Excel"""
with pd.ExcelWriter(f'{filename}.xlsx', engine='openpyxl') as writer:
for i, (headers, data) in enumerate(zip(self.headers_list, self.data)):
df = pd.DataFrame(data, columns=headers)
df.to_excel(writer, sheet_name=f'Table_{i+1}', index=False)
def save_json(self, filename):
"""保存为JSON"""
import json
output = {'tables': []}
for i, (headers, data) in enumerate(zip(self.headers_list, self.data)):
output['tables'].append({
'index': i,
'headers': headers,
'data': data
})
with open(f'{filename}.json', 'w', encoding='utf-8') as f:
json.dump(output, f, ensure_ascii=False, indent=2)
def run(self, url=None):
"""主执行函数"""
target_url = url or self.base_url
html = self.fetch_page(target_url)
if html:
tables = self.extract_tables(html)
if tables:
self.headers_list = [t['headers'] for t in tables]
self.data = [t['data'] for t in tables]
for i, table_info in enumerate(tables):
print(f"表格 {i+1}: {table_info['caption']}")
print(f" 列数: {len(table_info['headers'])}")
print(f" 行数: {len(table_info['data'])}")
return tables
else:
print("在页面中未找到表格")
return []
# 使用示例
if __name__ == "__main__":
scraper = TableScraper('https://example.com/page-with-tables')
tables = scraper.run()
if tables:
# 保存所有格式
scraper.save_to_file('csv', 'scraped_data')
scraper.save_to_file('excel', 'scraped_data')
scraper.save_to_file('json', 'scraped_data')
注意事项
- 遵守robots.txt:抓取前检查网站是否允许爬取
- 设置请求头:模拟真实浏览器访问
- 控制频率:添加延迟避免对服务器造成压力
- 异常处理:处理超时、连接错误等异常情况
- 数据验证:检查和验证提取的数据
- 编码问题:正确处理中文字符编码(如utf-8)
常见问题解决
- 动态加载数据:使用Selenium或Playwright
- 反爬机制:使用代理IP、添加延迟、模拟真人操作
- 复杂的表格结构:使用find_all + 条件判断
- 多种表格格式:设计通用函数或使用模式匹配
选择哪种方法取决于你的具体需求:静态页面用BeautifulSoup,需要JavaScript渲染的用Selenium,想要快速实现且页面简单的用Pandas的read_html。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播