从爬取到决策:Python爬虫与AI应用全链路开发实战

从爬取到决策:Python爬虫与AI应用全链路开发实战 摘要在AI大模型时代爬虫的价值已从“获取数据”升维为“构建AI决策系统的感知触角”。本文跳出传统爬虫教程的舒适区以“竞品价格监控智能定价建议”为实战案例完整演示从数据采集、清洗入库、RAG知识库构建到大模型决策输出的全链路工程。文章重点剖析了非结构化数据如何转化为AI可理解的语义向量以及如何让LLM基于实时爬取的数据做出可靠决策。附完整架构图与生产级代码框架适合希望将爬虫能力与AI应用结合的开发者阅读。一、 为什么你的爬虫还在“只爬不用”在CSDN上搜索“Python爬虫”90%的文章止步于requests BeautifulSoup把数据存进CSV或MySQL。但在2026年的技术语境下这种“采集即终点”的模式正快速贬值数据本身不值钱洞察才值钱爬了10万条商品价格如果没有分析模型它只是占用磁盘的字符串AI需要“活数据”大模型的训练数据有截止日期而业务决策依赖的是“此刻”的信息非结构化数据被浪费网页中的评论、描述、图片alt文本传统爬虫只提取字段丢弃了90%的语义信息新范式爬虫不再是独立工具而是AI Agent的实时感知模块。它负责回答一个核心问题“现在外部世界发生了什么”而AI负责回答“所以我们该怎么做”本文将以一个真实场景贯穿全文电商竞品价格监控系统。目标不是“爬到价格”而是“当竞品降价时系统自动给出调价建议并说明理由”。二、 全链路架构设计2.1 四层架构总览行动层: 输出与反馈数据层: 结构化语义化标注修正认知层: RAG LLM查询理解 检索增强LLM推理 Qwen2.5/GLM-4决策Prompt模板感知层: 智能采集调度器 APScheduler爬虫引擎 Scrapy/Requests反爬对抗 增量去重PostgreSQL 结构化存储ChromaDB 向量存储ETL管道: 清洗/分块/EmbeddingAPI/Webhook推送人工审核界面反馈回流优化2.2 关键设计决策层级选型理由采集Requests parsel轻量级竞品页面结构简单无需Scrapy重型框架结构化存储PostgreSQL JSONB兼顾关系查询与非结构化字段灵活性向量存储ChromaDB嵌入式部署零运维百万级向量足够Embeddingbge-m3-zh中文语义理解SOTA支持长文本LLMQwen2.5-72B-API国产模型中文能力强API成本可控调度APScheduler进程内调度避免Celery过度工程化核心原则每个组件都为“AI可消费”服务。爬虫输出的不是原始HTML而是经过清洗、带有元数据的结构化文档向量库索引的不是原文而是精心设计的语义块。三、 感知层为AI而生的爬虫3.1 与传统爬虫的三个本质区别维度传统爬虫AI导向爬虫输出格式CSV/数据库行带元数据的Markdown/JSON文档关注点字段完整性语义完整性上下文不丢失更新策略全量覆盖增量diff 变更标记错误处理跳过/重试记录失败原因供AI诊断3.2 采集代码核心片段importrequestsfromparselimportSelectorfromdatetimeimportdatetimeimporthashlibdefcrawl_product(url:str)-dict|None: 采集单个商品页输出AI友好的结构化文档 关键保留语义上下文而非仅提取字段 resprequests.get(url,headersHEADERS,timeout10)ifresp.status_code!200:return{error:fHTTP{resp.status_code},url:url}selSelector(resp.text)# 提取结构化字段titlesel.css(h1.product-title::text).get().strip()pricesel.css(.current-price::text).get().strip()description\n.join(sel.css(.product-desc p::text).getall()).strip()# ⭐ 关键构建AI可消费的文档格式doc{url:url,content_id:hashlib.md5(url.encode()).hexdigest(),title:title,price:price,description:description,# 保留原始页面快照用于溯源raw_html_snippet:sel.css(.product-info).get()[:2000],crawled_at:datetime.now().isoformat(),# 元数据帮助AI理解数据来源与时效性metadata:{source:competitor_site_a,category:extract_category(sel),last_modified:resp.headers.get(Last-Modified,),}}returndoc3.3 增量检测让AI知道“什么变了”AI决策最忌讳基于过时信息。每次采集后必须做diffdefdetect_changes(new_doc:dict,old_doc:dict)-dict: 返回变更摘要而非简单的新旧值对比 这个摘要将直接作为RAG检索的上下文 changes[]ifnew_doc[price]!old_doc[price]:changes.append({field:price,old:old_doc[price],new:new_doc[price],change_type:decreaseiffloat(new_doc[price])float(old_doc[price])elseincrease})ifnew_doc[description]!old_doc[description]:changes.append({field:description,summary:产品描述已更新,change_type:content_update})return{has_changes:len(changes)0,changes:changes,detected_at:datetime.now().isoformat()}⚠️避坑提醒不要对浮点价格直接用!比较。电商页面常有¥99.00vs¥99的格式差异。务必先标准化为Decimal再比较。四、 数据层让非结构化数据“可被AI理解”4.1 为什么不能直接把爬取的文本扔进向量库这是新手最常犯的错误。原始网页文本存在三大问题噪声干扰导航栏、广告、版权声明混入正文污染语义粒度失配整篇文档太长检索时命中无关段落句子太短缺乏上下文缺少锚点AI无法区分“这是价格信息”还是“这是用户评论”4.2 智能分块策略针对竞品监控场景我们采用语义感知分块而非固定长度切分defchunk_product_doc(doc:dict)-list[dict]: 按业务语义分块每块携带明确的类型标签 这让RAG检索可以按类型过滤 chunks[]# 块1: 价格信息高频查询对象chunks.append({content:f【价格】{doc[title]}当前售价{doc[price]},chunk_type:price,metadata:{**doc[metadata],content_id:doc[content_id]}})# 块2: 产品描述按段落分块保留上下文paragraphs[p.strip()forpindoc[description].split(\n)ifp.strip()]fori,parainenumerate(paragraphs):chunks.append({content:f【产品描述·段落{i1}】{para},chunk_type:description,metadata:{**doc[metadata],content_id:doc[content_id],para_index:i}})# 块3: 变更事件仅当有变更时生成ifdoc.get(change_summary,{}).get(has_changes):change_textformat_changes(doc[change_summary][changes])chunks.append({content:f【变更事件】{doc[title]}{change_text},chunk_type:change_event,metadata:{**doc[metadata],content_id:doc[content_id]}})returnchunks4.3 Embedding与入库fromchromadbimportPersistentClientfromsentence_transformersimportSentenceTransformer embedderSentenceTransformer(BAAI/bge-m3-zh)chromaPersistentClient(path./chroma_db)collectionchroma.get_or_create_collection(product_intel)defindex_chunks(chunks:list[dict]):embeddingsembedder.encode([c[content]forcinchunks])collection.upsert(ids[f{c[metadata][content_id]}_{i}fori,cinenumerate(chunks)],embeddingsembeddings.tolist(),documents[c[content]forcinchunks],metadatas[c[metadata]forcinchunks])性能提示bge-m3-zh单次encode建议batch_size32GPU上约5ms/条。CPU上建议用onnxruntime加速速度提升3-5倍。五、 认知层让LLM基于实时数据做决策5.1 RAG检索精准找到AI需要的上下文用户问“竞品A最近降价了吗我们该怎么应对”检索不能只靠语义相似度defretrieve_for_decision(query:str,product_name:str)-list[str]: 混合检索语义 元数据过滤 时间排序 确保AI拿到的是相关、最新、完整的信息 resultscollection.query(query_texts[query],n_results8,where{$and:[{source:competitor_site_a},# 只检索最近7天的数据{crawled_at:{$gte:seven_days_ago()}}]},include[documents,metadatas,distances])# 后处理去重 按chunk_type排序变更事件优先seen_idsset()prioritized[]type_priority{change_event:0,price:1,description:2}fordoc,meta,distinzip(results[documents][0],results[metadatas][0],results[distances][0]):cidmeta[content_id]ifcidnotinseen_idsanddist0.5:# 距离阈值过滤噪声seen_ids.add(cid)prioritized.append((type_priority.get(meta.get(chunk_type,),9),doc))return[docfor_,docinsorted(prioritized)]5.2 决策Prompt工程约束LLM的输出边界这是全链路中最关键的环节。放任LLM自由发挥等于制造幻觉机器DECISION_PROMPT你是一名电商定价分析师。基于以下实时竞品情报给出调价建议。 ## 可用情报来自实时爬取非训练数据 {context} ## 我方产品信息 - 产品名称: {our_product} - 当前售价: {our_price} - 成本价: {our_cost} - 毛利率底线: {min_margin}% ## 输出要求 1. 【事实摘要】仅基于上述情报总结竞品动态不得编造 2. 【调价建议】给出具体价格或价格区间附带计算过程 3. 【风险提示】指出建议可能带来的负面影响 4. 【置信度】高/中/低并说明理由 5. 若情报不足以支撑决策明确说信息不足建议补充采集XXX 禁止使用根据我的知识一般来说等脱离给定情报的表述。 5.3 调用LLM并解析结构化输出importjsonfromopenaiimportOpenAI clientOpenAI(base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1)defgenerate_decision(query:str,our_product_info:dict)-dict:context_docsretrieve_for_decision(query,our_product_info[name])context\n---\n.join(context_docs)responseclient.chat.completions.create(modelqwen-plus,messages[{role:system,content:DECISION_PROMPT.format(contextcontext,**our_product_info)},{role:user,content:query}],temperature0.1,# 决策场景低温减少随机性response_format{type:json_object}# 强制JSON输出)try:decisionjson.loads(response.choices[0].message.content)# ✅ 关键附加溯源信息让人工审核可追溯decision[_sources]context_docs[:3]decision[_model]qwen-plusdecision[_generated_at]datetime.now().isoformat()returndecisionexceptjson.JSONDecodeError:return{error:LLM输出非JSON,raw:response.choices[0].message.content}六、 行动层与闭环优化6.1 人工审核不是可选项AI决策永远需要人在回路Human-in-the-Loop。设计审核界面时务必展示LLM引用的原始数据块可点击跳转到源网页置信度与风险等级历史同类决策的执行效果6.2 反馈回流让系统越用越准审核员的“采纳/拒绝/修改”操作是最珍贵的标注数据defrecord_feedback(decision_id:str,action:str,corrected_price:floatNone): 反馈数据用于两个目的 1. 评估LLM决策准确率监控指标 2. 未来微调/Rerank模型训练长期优化 db.execute( INSERT INTO decision_feedback (decision_id, action, corrected_price, created_at) VALUES (%s, %s, %s, NOW()) ,(decision_id,action,corrected_price))七、 工程避坑清单陷阱后果解决方案爬虫频率过高触发封禁AI断粮决策基于过期数据代理池 自适应限速 多源冗余向量库未设TTL陈旧数据污染检索结果ChromaDB metadata filter 定期清理任务Prompt未约束输出格式下游解析失败系统中断JSON Mode Pydantic校验 重试机制未记录Token消耗月底账单爆炸每次调用记录input/output tokens设预算告警爬虫与AI耦合过紧改采集逻辑要重写AI模块通过消息队列/数据库解耦接口契约化八、 总结从工具到系统的思维跃迁回顾全链路我们实际上完成了一次认知升级爬虫从“数据搬运工”变为“AI感知器官”数据库从“存储仓库”变为“语义记忆体”LLM从“聊天机器人”变为“受约束的决策引擎”开发者从“写脚本的人”变为“AI系统架构师”这条链路的价值不在于任何单一环节的技术深度而在于端到端的信息流转效率。当竞品降价5分钟后你的系统已经给出了带溯源的调价建议——这才是“从爬取到决策”的真正含义。最后的忠告不要追求技术栈的时髦。如果你的业务只需要规则引擎就能解决就不要硬上LLM。AI是手段决策质量才是目的。先用最简单的方案跑通闭环再逐步替换更强大的组件。参考资料ChromaDB DocumentationBGE-M3 Technical ReportRAG Best Practices - LangChain DocsQwen2.5 API Reference免责声明本文所述爬虫技术请严格遵守目标网站robots.txt及相关法律法规。AI决策仅供参考不构成商业建议。作者不对因使用本文方案产生的任何损失负责。如果这篇文章帮你打通了爬虫与AI的工程链路欢迎点赞收藏。有具体的业务场景想讨论可以在评论区描述你的需求我会给出针对性的架构建议。