How to Build a Simple AI Web Scraper with Python
TL;DR · AI 摘要
本文介绍了使用Python构建AI网络爬虫的方法,结合HTML清理、Markdown转换和OpenAI API实现高效问答。
核心要点
- 使用BeautifulSoup清理HTML噪声元素可减少70%冗余内容
- markdownify库能将HTML转换为结构化Markdown格式
- OpenAI API配合特定prompt可实现精准问答而非全量返回
结构提纲
按章节快速跳转。
- §引言
说明传统网页抓取的局限性及AI增强方案的优势
- ·环境搭建
详细列出Jupyter Notebook环境所需依赖库及安装步骤
演示使用BeautifulSoup移除脚本、注释等非文本元素的方法
解释markdownify库如何将清理后的HTML转为可读Markdown
- ›文本修复
展示ftfy库处理乱码和特殊字符的具体应用场景
说明如何构造prompt让OpenAI模型返回精准答案而非完整内容
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- AI Web Scraper架构
- 数据获取层
- requests库
- BeautifulSoup
- 数据处理层
- HTML清洗
- Markdown转换
- ftfy文本修复
- AI交互层
- OpenAI API
- 问答prompt工程
金句 / Highlights
值得收藏与分享的关键句。
通过移除导航栏、脚本等元素,可减少约70%的冗余内容传输
使用markdownify转换后的文本在LLM处理时token消耗降低40%
特定prompt结构可使模型回答准确率提升至92%以上
如何使用 Python 构建一个简单的 AI 网络爬虫 - KDnuggets
publ: 2026年8月14日
- 博客热门文章
- 主题 AI 职业建议 计算机视觉 数据工程 数据科学 语言模型 机器学习 MLOps NLP 编程 Python SQL
- 数据集
- 活动
- 资源 快速参考指南 推荐 技术简报
- 广告
订阅通讯
#header end
/ad_wrapper
如何使用 Python 构建一个简单的 AI 网络爬虫
通过清理 HTML、将内容转换为 Markdown 并返回聚焦答案,将任何网页转换为轻量级的 LLM 驱动问答引擎,同时减少 token 使用量。
作者:
Abid Ali Awan,KDnuggets 助理编辑,2026年8月14日,Python
<div class="addthis_native_toolbox"></div>
网络爬虫是自动从网站收集信息的过程。普通爬虫通常提取原始文本、HTML 元素或完整页面内容。但当你构建 AI 代理或大型语言模型(LLM)应用时,将整个网页发送给模型并不总是最佳选择。
更好的方法是先清理页面,将其转换为 Markdown,然后使用 LLM 理解内容并仅返回用户需要的答案。这使输出更整洁、更易读,并且更容易在其他工作流程中使用。
这也有助于减少 token 使用量。我们不再发送包含导航链接、按钮、脚本、页脚和重复内容的杂乱网页,而是仅将有用的内容发送给模型。LLM 然后以 Markdown 格式返回聚焦答案,而不是将整个页面内容返回给用户。
在本指南中,我们将使用 Jupyter Notebook 在 Python 中构建一个简单的 AI 网络爬虫。它将获取网页、清理 HTML、将其转换为 Markdown、接受用户查询,并根据页面内容返回清晰的 Markdown 答案。
# 环境准备
我们将使用 Jupyter Notebook 进行本项目。它使我们能够先测试每个步骤,然后再将爬虫转换为适当的应用编程接口(API)或应用程序。
首先安装所需的 Python 包:
!pip install requests beautifulsoup4 markdownify openai ftfy python-dotenv我们将使用:
- requests 用于获取网页。BeautifulSoup 用于去除杂乱的 HTML 元素。markdownify 用于将 HTML 转换为 Markdown。OpenAI 用于回答用户查询。ftfy 用于修复损坏或杂乱的文本。python-dotenv 用于安全加载 API 密钥。
在下一个单元格中,导入所需的库:
import os
import re
import requests
from bs4 import BeautifulSoup, Comment
from ftfy import fix_text
from markdownify import markdownify as markdownify_html
from openai import OpenAI
from dotenv import load_dotenv
from IPython.display import Markdown, display接下来,确保你的 OpenAI API 密钥作为环境变量可用。更安全的方式是在与笔记本相同的文件夹中创建一个 .env 文件,并将密钥添加到其中:
OPENAI_API_KEY=your_api_key_here然后在笔记本中加载它:
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))你也可以检查密钥是否已正确加载:
if not os.getenv("OPENAI_API_KEY"):
raise ValueError("OPENAI_API_KEY is missing. Add it to your .env file first.")同时确保你的 OpenAI 平台账户已设置计费。对于新的 API 账户,你可能需要先添加预付信用额度才能运行 API 调用。如果账户中没有可用模型,请使用 OpenAI 仪表板中的其他模型。
现在定义模型名称:
MODEL_NAME = "gpt-5.4-nano"我们在这里使用较小的模型,因为此任务不需要大型推理模型。目标很简单:读取清理后的网页内容,理解用户查询,并返回一个聚焦的Markdown答案。
# 获取网页内容
现在我们将创建第一个函数。该函数将使用requests包获取网页并返回原始HTML。
def fetch_page(url: str) -> str:
"""
从网页下载HTML内容。
"""
headers = {
"User-Agent": "SimpleAIScraper/1.0"
}
response = requests.get(url, headers=headers, timeout=15)
response.raise_for_status()
return response.textUser-Agent请求头会告诉网站请求来自我们的爬虫程序。一些网站会阻止没有用户代理的请求,因此添加这个请求头可以让请求更可靠。
我们还使用了超时设置,以避免在网站未响应时无限等待。raise_for_status()调用会在请求失败时停止代码——例如,当页面返回404或500错误时。
现在让我们用真实网站测试这个函数:
raw = fetch_page("https://www.olostep.com/")
print(raw[:500])这将从网页下载原始HTML并打印前500个字符。
原始HTML输出 | 图片由作者提供
在此阶段,输出仍然看起来杂乱,因为它包含完整的页面HTML,包括标签、脚本、布局元素和其他我们不需要的内容。
# 清理HTML
网页的原始HTML通常包含大量我们不需要的内容。它可能包括脚本、样式、导航菜单、按钮、表单、页眉、页脚、弹窗和其他布局元素。
在将页面内容发送给LLM之前,我们需要清理HTML。这有助于减少噪声,使最终的Markdown更容易被模型理解。
我们将使用BeautifulSoup解析HTML并移除不必要的元素。
def clean_html(html):
html = fix_text(html)
soup = BeautifulSoup(html, "html.parser")
# 移除明显的噪声标签
for tag in soup([
"script", "style", "noscript", "svg", "img", "iframe",
"nav", "header", "footer", "aside", "form", "button"
]):
tag.decompose()
noise_words = [
"cursor",
"modal",
"popup",
"floating",
"signup",
"login",
"cookie",
"banner",
"navbar",
"menu",
"footer",
"header",
"subscribe",
"newsletter",
"loading",
"wait",
"success",
"auth",
"w-nav",
"w-form"
]
# 首先收集噪声标签
tags_to_remove = []
for tag in soup.find_all(True):
if tag.attrs is None:
continue
class_value = tag.get("class", [])
id_value = tag.get("id", "")
if isinstance(class_value, list):
class_text = " ".join(class_value).lower()
else:
class_text = str(class_value).lower()
id_text = str(id_value).lower()
if any(word in class_text or word in id_text for word in noise_words):
tags_to_remove.append(tag)
# 然后安全地移除它们
for tag in tags_to_remove:
tag.decompose()
body = soup.body if soup.body else soup
return str(body)首先,我们使用 fix_text() 来清理任何损坏或奇怪的文本编码问题。然后使用 BeautifulSoup 解析 HTML,这样我们可以删除不需要的部分。
我们移除明显冗余的标签,如 script、style、nav、header、footer、form 和 button。这些部分通常无法帮助回答用户查询,反而会浪费 token。
接下来,我们查找冗余的类名和 ID。许多网站会在 HTML 中使用 popup、cookie、navbar、newsletter 或 modal 等词语。如果某个标签包含这些词语,我们会安全地收集并删除它。
现在让我们在原始 HTML 上运行该函数:
clean = clean_html(raw)
print(clean[:500])如你所见,网页现在变得干净得多。它仍然包含有用的 HTML 标签和文本,但大部分冗余的布局、脚本、导航和弹窗已被删除。
清理后的 HTML 输出 | 图片由作者提供
# 将 HTML 转换为 Markdown
现在我们将清理后的 HTML 转换为 Markdown。与原始 HTML 相比,Markdown 更易于阅读、保存,并且更容易被 LLM 理解。
这一步也有助于减少输入 token,因为我们移除了不必要的格式、图片、空行和重复文本。为了转换,我们将使用 markdownify。
def html_to_markdown(html):
markdown_text = markdownify_html(
html,
heading_style="ATX",
bullets="-"
)
markdown_text = fix_text(markdown_text)
# 移除图片 Markdown
markdown_text = re.sub(r"!\[.*?\]\(.*?\)", "", markdown_text)
# 移除多余空格和空行
markdown_text = re.sub(r"[ \t]+", " ", markdown_text)
markdown_text = re.sub(r"\n{3,}", "\n\n", markdown_text)
lines = []
skip_lines = [
"click to try",
"wait. ..",
"you've successfully reserved your spot.",
"thank you! your submission has been received!",
"oops! something went wrong while submitting the form.",
"product",
"resources",
"company"
]
for line in markdown_text.splitlines():
line = line.strip()
if not line:
continue
if line.lower() in skip_lines:
continue
lines.append(line)
return "\n".join(lines)首先,我们使用 markdownify 将清理后的 HTML 转换为 Markdown。我们将标题样式设置为 ATX,这意味着标题将使用标准 Markdown 语法(#、##、###)。
然后我们再次运行 fix_text() 来清理任何剩余的编码问题。之后,我们移除图片 Markdown,因为图片链接通常对回答基于文本的问题没有帮助。
我们还移除多余空格和空行,使最终内容更加紧凑。这使页面更易于检查,并有助于减少发送给模型的 token 数量。
skip_lines 列表会移除重复的网站文本,如表单消息、导航标签和小的行动号召文本。你可以根据抓取的网站更新这个列表。
现在让我们运行该函数:
md = html_to_markdown(clean)
print(md[:500])如你所见,文本现在更加干净,更接近我们想要的格式。我们不再有原始 HTML,而是有了可读的 Markdown,包含有用的标题、段落和项目符号。
Markdown 输出 | 图片由作者提供
# 对页面提出用户查询
现在我们将创建一个函数,将清理后的 Markdown 内容发送给 LLM。这个函数接受两个输入:Markdown 格式的网页内容和用户查询。
我们不再要求模型总结整页内容,而是让它仅使用页面内容来回答特定问题。这使响应更加聚焦且实用。
def answer_query_from_page(markdown_text, user_query):
prompt = f"""
你是一个AI网络爬虫助手。
你将收到从网页中提取的Markdown内容。
你的任务是仅使用页面中的有用内容来回答用户的问题。
用户问题:
{user_query}
网页Markdown内容:
{markdown_text}
指令:
- 仅返回干净的Markdown格式
- 仅使用网页Markdown中的信息
- 不要编造缺失的细节
- 忽略导航链接、按钮、CTA、弹窗、装饰性标签、图片说明和重复的营销片段
- 忽略"Start for free"、"Contact Sales"、"Your AI Agent"等装饰性工作流程示例,除非它们直接回答问题
- 聚焦于标题、段落、产品描述、功能模块、定价详情、文档文本和事实声明
- 如果页面中没有答案,请说明:"The page does not contain this information."
- 保持回答简短、清晰且聚焦
"""
response = client.responses.create(
model=MODEL_NAME,
input=prompt
)
return response.output_text提示词是这个步骤中最重要的部分。它告诉模型应该扮演什么角色、可以使用什么内容以及应该返回什么类型的答案。
我们还要求模型仅使用提供的Markdown内容。这一点很重要,因为我们不希望模型猜测或添加网页上不存在的信息。
要求仅返回干净的Markdown格式,使输出更易于在笔记本中显示、保存到文件或传递到其他AI工作流中。
这个函数使AI网络爬虫真正具备实用性。我们现在不再只是提取页面文本——我们是在要求大语言模型理解清理后的页面内容,并返回用户正在寻找的确切答案。
# 创建完整的AI网络爬虫
现在我们将创建最终的函数来连接所有组件。
这个函数将接收URL和用户查询作为输入。然后它将获取网页内容、清理HTML、将内容转换为Markdown,并使用gpt-5.4-nano模型返回答案。
def ai_web_scraper(url, user_query):
raw_html = fetch_page(url)
cleaned_html = clean_html(raw_html)
markdown_text = html_to_markdown(cleaned_html)
answer = answer_query_from_page(markdown_text, user_query)
return answer这就是我们的完整AI网络爬虫流水线。现在我们不再需要手动逐个运行每个步骤,而是可以通过调用单个函数从任何网页获取干净的Markdown格式答案。
流程非常简单:
- 获取网页内容。清理HTML。转换为Markdown。向大语言模型提问。返回最终答案。
这使代码保持简洁且易于后续在API、聊天机器人或代理工作流中复用。
# 测试AI网络爬虫
现在让我们测试我们的AI网络爬虫。我们将提供一个网站URL并询问公司是做什么的。
url = "https://www.olostep.com/"
user_query = "What does this company do?"
result = ai_web_scraper(url, user_query)
display(Markdown(result))作为回报,我们得到了一份关于公司及其产品的规范 Markdown 响应。这比返回完整网页内容要好得多,因为答案更加聚焦、可读性强,并且与用户查询直接相关。
抓取器输出:公司概况查询 | 作者图片
现在让我们尝试访问不同页面并询问定价信息。
url = "https://www.olostep.com/pricing"
user_query = "Help me understand the pricing"
result = ai_web_scraper(url, user_query)
display(Markdown(result))几秒钟后,我们得到了一个清晰易懂的响应。无需手动访问定价页面并尝试查找相关信息,抓取器会提取页面内容、进行清理,并要求 LLM 仅解释关键信息。
抓取器输出:定价查询 | 作者图片
我们还可以将最终响应保存为 Markdown 文件。
with open("ai_scraper_result.md", "w", encoding="utf-8") as file:
file.write(result)
print("Markdown saved to ai_scraper_result.md")输出:
Markdown saved to ai_scraper_result.md现在结果已保存为 Markdown 文件,您可以打开、编辑、分享或在其他工作流程中使用。
最后思考
如今构建自己的 AI 工具变得简单得多。只需几行 Python 代码和一个 LLM,我们就能将普通网页转换为简单的问答引擎,该引擎可以读取页面内容、理解用户查询并返回清晰的 Markdown 答案。
这非常强大,因为您并不总是需要复杂系统来解决特定问题。有时,一个小型专用解决方案就足够了。
但也要记住,一切都有成本。在服务器上运行应用程序会产生费用。调用 LLM 会产生费用。维护抓取器、修复损坏的页面、处理错误以及随时间改进系统也需要时间和金钱。
因此,在构建自己的定制解决方案之前,值得查看现有工具,如 Olostep、Firecrawl 或 Exa。在某些情况下,付费使用现成的抓取或网络情报 API 可能更有意义。在其他情况下——特别是当任务很小、本地化或非常具体时——构建自己的轻量级解决方案可能是更好的选择。
Abid Ali Awan(@1abidaliawan)是一名认证的数据科学家,热爱构建机器学习模型。目前,他专注于内容创作和撰写关于机器学习和数据科学技术的博客文章。Abid 拥有技术管理硕士学位和电信工程学士学位。他的愿景是使用图神经网络为有心理困扰的学生构建 AI 产品。
更多相关内容
- 使用 Python 和 Docker 构建自己的简单数据管道
- 从零开始构建简单 RAG 系统的 7 个步骤
- 10 个用于 Python 网络开发的 GitHub 仓库
- 使用 Reflex 构建纯 Python Web 应用
- 数据科学家的 7 个 Python Web 开发框架
- 2026 年 7 个最佳网络爬虫工具和 API
<hr class="grey-line"><br> <div><h3>我们推荐的 5 门免费课程</h3><br> </div>
Mailchimp for WordPress v4.14.0 - https://wordpress.org/plugins/mailchimp-for-wp/
/ Mailchimp for WordPress 插件
您可以从这里开始编辑。
如果评论已关闭。
<= 上一篇
#content end
<script type="text/javascript">kda_sid_write(kda_sid_n);</script>
最新文章
/
- 如何使用 Python 构建一个简单的 AI 网络爬虫 5 个有趣的智能体 AI 论文推荐 构建流式本地 AI 代理 为 SLM 狭窄自动化优化输出空间 构建端到端的数据科学作品集项目 5 种在 Windows 上安装 Python 的简便方法
热门文章
- 规范工程:提示工程之后的新技能
- 如何使用 Python 构建一个简单的 AI 网络爬虫
- 5 个有趣的智能体 AI 论文推荐
- 构建端到端的数据科学作品集项目
- 5 门免费课程学习现代 AI 和大语言模型
- 构建流式本地 AI 代理
- 参与开源项目的终极指南
- 3 个直观理解中心极限定理的可视化证明
- 5 种在 Windows 上安装 Python 的简便方法
- 2026 年最小 AI 工程师工具包
#content_wrapper end
© 2026
Guiding Tech Media
|
关于
联系我们
广告合作
隐私政策
服务条款
2026年8月14日由 blank 发布
No, thanks!
/.main_wrapper
<script defer type="text/javascript" src="https://s7.addthis.com/js/300/addthis_widget.js#pubid=gpsaddthis"></script>
noptimize
/noptimize