#!/usr/bin/env python3
"""scrape_supplier_quotes.py
从本地运行的 http://localhost:8000/supplier_quotes.html 页面中提取
静态 HTML 表格数据,并保存为 Excel 文件(supplier_quotes.xlsx)。
页面使用静态 HTML 表格展示数据,直接解析 <tbody> 即可获取所有数据。
依赖: requests beautifulsoup4 lxml pandas openpyxl
安装: pip install requests beautifulsoup4 lxml pandas openpyxl
"""
import sys
import re
from pathlib import Path
try:
import requests
from bs4 import BeautifulSoup
import pandas as pd
except ImportError:
sys.stderr.write(
"缺少依赖,请执行: pip install requests beautifulsoup4 lxml pandas openpyxl\n"
)
sys.exit(1)
# ---------------------------------------------------------------------------
# 配置
# ---------------------------------------------------------------------------
URL = "http://localhost:8099/supplier_quotes.html" # 爬取目标页面地址
OUTPUT_XLSX = Path(__file__).with_name("供应商列表.xlsx") #输出到代码所在的文件夹,可以指定输出路径 示例:Path("D:/python/供应商列表.xlsx")
# 表头顺序必须和 HTML 表格中的列顺序一致(共 11 列)
HEADERS = [
"供应商名称",
"社会统一信用代码",
"报价(元/吨)",
"交货时间(天)",
"履约率(%)",
"资产负债率(%)",
"质量评分",
"服务评分",
"地址",
"法人代表人",
"联系电话",
]
def fetch_page(url: str) -> str:
"""下载页面 HTML,返回文本内容。"""
try:
resp = requests.get(url, timeout=15)
resp.raise_for_status()
resp.encoding = resp.apparent_encoding
return resp.text
except requests.RequestException as exc:
sys.stderr.write(f"请求页面失败: {exc}\n")
sys.exit(1)
def extract_table_data(html: str):
"""从页面的 HTML 表格 <tbody> 中提取数据并返回 Python 列表。"""
soup = BeautifulSoup(html, "lxml")
# 查找表格
table = soup.find("table", id="supplierTable")
if not table:
sys.stderr.write("未在页面中找到 id='supplierTable' 的表格。\n")
sys.exit(1)
# 查找 tbody
tbody = table.find("tbody")
if not tbody:
sys.stderr.write("表格中没有 <tbody> 元素。\n")
sys.exit(1)
# 提取所有行
rows = tbody.find_all("tr")
if not rows:
sys.stderr.write("表格 <tbody> 中没有数据行。\n")
sys.exit(1)
data_rows = []
for row in rows:
cells = row.find_all("td")
if len(cells) != 11:
sys.stderr.write(f"警告: 发现不完整的行(列数: {len(cells)}),跳过。\n")
continue
# 提取每个单元格的文本内容
row_data = []
for i, cell in enumerate(cells):
text = cell.get_text(strip=True)
# 特殊处理:
# 1. 供应商名称 (列 0) - 直接使用
# 2. 社会统一信用代码 (列 1) - 提取 <span class="supplier-code"> 的内容
# 3. 报价 (列 2) - 去除 ¥ 符号和逗号
# 4. 履约率 (列 4) - 提取 <span class="rate-badge"> 的内容
if i == 1: # 社会统一信用代码
code_span = cell.find("span", class_="supplier-code")
text = code_span.get_text(strip=True) if code_span else text
elif i == 2: # 报价
text = text.replace("¥", "").replace(",", "")
elif i == 4: # 履约率
rate_span = cell.find("span", class_="rate-badge")
text = rate_span.get_text(strip=True) if rate_span else text
row_data.append(text)
data_rows.append(row_data)
return data_rows
def write_excel(xlsx_path: Path, rows):
"""使用 pandas 将数据写入 Excel(带列标题)。"""
df = pd.DataFrame(rows, columns=HEADERS)
df.to_excel(xlsx_path, index=False, engine="openpyxl")
def main():
print(f"Fetching page from: {URL}")
html = fetch_page(URL)
print("Extracting table data from HTML...")
data_rows = extract_table_data(html)
print(f"Found {len(data_rows)} data rows.")
print(f"Writing Excel to: {OUTPUT_XLSX}")
write_excel(OUTPUT_XLSX, data_rows)
print("Done.")
if __name__ == "__main__":
main()