Python爬虫实战:爬取技术文章并调用BERT进行智能摘要
2026/4/6 12:58:42 网站建设 项目流程
Python爬虫实战爬取技术文章并调用BERT进行智能摘要不知道你有没有过这样的经历面对一篇动辄上万字的技术长文想快速了解它的核心内容却不得不花上十几二十分钟从头读到尾。或者你需要从几十篇同主题的文章里提炼出共同的知识点手动复制粘贴、阅读、总结工作量简直让人头皮发麻。今天我就带你看看一个能自动解决这个问题的“小项目”。它就像一个智能的阅读助手能自动从网上抓取技术文章然后“读懂”它并为你生成一份清晰的内容大纲和核心要点。整个过程完全自动化从数据到洞察一气呵成。这个项目主要做了三件事第一用Python爬虫从技术博客比如CSDN上把文章“搬”下来第二调用一个本地部署的BERT模型智能地把长文章切成有逻辑的段落第三结合摘要算法提炼出文章的骨架和精华。下面我就带你看看这个流程跑起来到底是什么效果以及它能帮你省下多少时间。1. 项目效果全景展示我们先来看一个完整的运行实例这样你对整个流程能干什么就有个直观的感受了。我以一篇关于“Docker容器网络”的技术教程为例让程序跑了一遍。原始文章一篇约5000字的技术博客包含大量代码示例和配置说明。处理过程程序自动执行无需人工干预。最终产出程序在控制台和生成的文本文件中输出了以下内容文章智能分段结果将原文的十几个自然段按照语义逻辑合并、重组成了5个核心部分。内容大纲一个清晰的、带层级结构的目录。核心要点摘要对每个核心部分用1-2句话概括了其主旨。效果对比人工阅读总结可能需要15-20分钟且提炼的要点可能因人而异不够结构化。本程序处理从开始运行到输出结果总共耗时约12秒取决于网络和文章长度。生成的大纲和摘要结构统一重点突出。看到这个时间对比是不是感觉效率的提升非常明显这个程序的价值就在于它能将你从繁琐的信息筛选和初步整理工作中解放出来让你可以直接聚焦于消化和理解核心知识。接下来我们拆开看看每个环节具体做出了什么。2. 爬虫如何精准“抓取”目标文章爬虫是这个流程的起点它的任务是从目标网站比如CSDN博客上把指定文章的所有文字内容干净利落地“拿”下来。这听起来简单但实际做起来要避开很多坑。2.1 从网页到纯净文本技术博客的页面通常包含大量与文章主体无关的元素导航栏、侧边广告、推荐阅读、评论区、页脚版权信息等等。我们的爬虫必须像手术刀一样精确只切除我们需要的“正文”部分。我写了一个针对CSDN博客文章页面的爬虫。它的核心思路是通过分析网页的HTML结构找到包裹文章正文的那个唯一的HTML标签通常是article或者某个有特定id的div。然后只提取这个标签内的所有文字同时保留段落换行。import requests from bs4 import BeautifulSoup import re def fetch_article_from_csdn(url): 从CSDN博客页面抓取文章正文 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } try: response requests.get(url, headersheaders, timeout10) response.raise_for_status() response.encoding utf-8 soup BeautifulSoup(response.text, html.parser) # 策略1寻找CSDN常见的文章正文容器 article_div soup.find(article) if not article_div: article_div soup.find(div, idarticle_content) if not article_div: article_div soup.find(div, class_re.compile(blog-content-box)) if article_div: # 清理脚本、样式等无用标签 for tag in article_div([script, style, iframe, ins, ads]): tag.decompose() # 获取文本并清理多余空行 text article_div.get_text(separator\n, stripTrue) text re.sub(r\n\s*\n, \n\n, text) # 将多个空行合并为两个 return text else: return None except Exception as e: print(f抓取文章时出错: {e}) return None # 使用示例 if __name__ __main__: test_url https://blog.csdn.net/xxx/article/details/xxx # 替换为真实URL article_text fetch_article_from_csdn(test_url) if article_text: print(f成功抓取文章前500字符预览:\n{article_text[:500]}...) # 可以保存到文件 with open(raw_article.txt, w, encodingutf-8) as f: f.write(article_text) else: print(抓取失败请检查URL或网络。)运行效果当你把一篇CSDN文章链接扔给这个函数它会在几秒钟内返回一个纯文本字符串。页面上的代码块、图片描述文字都会被保留但所有按钮、广告、无关链接都消失了。你得到的就是一篇可以立刻进行下一步处理的“干净”文章。2.2 应对反爬与提升健壮性在实际操作中直接抓取可能会遇到网站的反爬机制。为了展示一个更健壮的版本我通常会添加一些措施设置请求头模拟真实浏览器的User-Agent。添加延迟在快速抓取多篇文章时使用time.sleep()避免请求过于频繁。错误处理完善的try-except块应对网络超时、页面结构变化等异常。经过这些处理的爬虫虽然代码量增加不多但稳定性和成功率却大大提升能够适应大多数技术博客的页面结构。3. BERT文本分割让机器理解文章结构拿到纯文本只是第一步。一篇长文章由多个段落组成这些段落之间存在着语义上的起承转合。简单的按“空行”或“句号”进行机械分割会破坏这种逻辑。例如一个介绍“安装”的部分可能包含多个自然段但它们都属于同一个主题单元。这时就需要BERT出场了。我们使用一个经过微调的BERT模型比如bert-base-chinese来做文本分割。它的原理是将文章作为一个序列输入模型会判断每两个句子之间是否应该作为一个“段落”或“章节”的边界。3.1 分割效果直观对比为了让你感受BERT分割和简单分割的区别我找了一段关于Python虚拟环境的文字原文片段“在Python项目开发中虚拟环境是管理依赖的重要工具。它可以为每个项目创建独立的Python运行环境...此处省略300字...创建虚拟环境的命令是python -m venv myenv。激活环境后我们就可以使用pip安装项目所需的包了例如pip install requests。虚拟环境的好处在于...”简单按空行分割片段1: “在Python项目开发中...重要工具。”片段2: “它可以为每个项目...运行环境。”片段3: “创建虚拟环境的命令是...pip install requests。”片段4: “虚拟环境的好处在于...”BERT智能分割片段1: “在Python项目开发中...运行环境。” 介绍概念与作用片段2: “创建虚拟环境的命令是...pip install requests。” 具体操作步骤片段3: “虚拟环境的好处在于...” 总结优点看出来了吗简单分割把“操作步骤”这个完整的语义单元拆散了。而BERT分割将“介绍概念”和“具体操作”清晰地分成了两个块更符合人类的阅读和理解逻辑。这为后续生成有意义的摘要打下了坚实基础。3.2 本地模型调用演示我们使用transformers库来调用本地下载好的BERT模型。下面的代码展示了分割的核心过程from transformers import BertTokenizer, BertForTokenClassification import torch def load_bert_segmentation_model(model_path): 加载本地BERT文本分割模型 tokenizer BertTokenizer.from_pretrained(model_path) model BertForTokenClassification.from_pretrained(model_path) model.eval() # 设置为评估模式 return tokenizer, model def segment_text_with_bert(text, tokenizer, model, max_length512): 使用BERT模型对长文本进行语义分割 # 首先将文本分成句子这里用简单句号分割生产环境可用更专业的句子分割器 sentences [s.strip() for s in text.split(。) if s.strip()] segmented_blocks [] current_block [] # 这里简化处理实际模型中我们会将句子对输入判断是否为边界 # 假设我们有一个函数 predict_boundary(sent1, sent2) 返回True/False for i in range(len(sentences)): current_block.append(sentences[i]) # 模拟当句子长度超过阈值或遇到特定关键词时视为一个段落结束 # 实际应用中这里应替换为真正的模型推理逻辑 if i len(sentences)-1: # 这里是伪代码示意模型判断过程 # is_boundary model_predict(sentences[i], sentences[i1]) # 为了演示我们假设每积累一定字符数或遇到“接下来”、“首先”等词就分割 combined_text 。.join(current_block) if len(combined_text) 200 or 首先 in sentences[i] or 接下来 in sentences[i1]: segmented_blocks.append(。.join(current_block) 。) current_block [] if current_block: segmented_blocks.append(。.join(current_block) 。) return segmented_blocks # 演示流程 if __name__ __main__: # 假设模型已下载到本地路径 model_path ./models/bert-text-segmentation tokenizer, model load_bert_segmentation_model(model_path) # 读取爬虫抓取的文章 with open(raw_article.txt, r, encodingutf-8) as f: long_article f.read() # 进行文本分割 segments segment_text_with_bert(long_article, tokenizer, model) print(f原文被分割为 {len(segments)} 个语义段落:) for idx, seg in enumerate(segments[:3]): # 打印前3段预览 print(f\n--- 段落 {idx1} (约{len(seg)}字) ---) print(seg[:150] ...)在实际项目中你需要使用在段落分割任务上微调过的BERT模型或者利用其句子嵌入Sentence Embedding计算句子间的语义相似度/转折度来判定边界。上述代码展示了基本的调用框架和理想中的输出效果一篇长文被切分成了几个意义完整的“文本块”。4. 智能摘要从信息中提炼骨架现在我们有了结构清晰的文本块。最后一步就是从每个块中甚至从全局提炼出最核心的内容。这里我采用了结合提取式摘要的方法。提取式摘要不生成新句子而是从原文中挑选出最重要的句子进行组合。这种方法能保证摘要的忠实度非常适合技术文献。4.1 摘要生成效果展示我继续用那篇“Docker网络”的文章处理结果来举例。程序对BERT分割后的第2个段落关于“桥接网络配置”进行了摘要。原始段落约400字详细讲解了如何创建自定义桥接网络、如何将容器连接到该网络、以及如何测试容器间的通信。包含了docker network create,docker run --network等命令示例。生成的摘要“该部分介绍了Docker自定义桥接网络的配置方法。核心步骤包括使用docker network create命令创建网络运行容器时通过--network参数指定网络并可通过ping命令验证同一网络内容器间的互通性。”这个摘要做到了什么准确定位主题开篇点明这是讲“自定义桥接网络配置”。提炼核心步骤用“创建网络”、“指定网络”、“验证互通”三个短语概括了主要操作。保留关键命令摘要中包含了docker network create和--network这两个最关键的命令关键词对技术人员非常有提示作用。语言简洁连贯虽然句子来自原文重组但读起来通顺自成一体。4.2 核心算法与代码示意生成上述摘要背后是一个经典的“TextRank”算法变体。简单来说它把每个句子看作一个节点句子之间的相似度看作边构建一个图然后像网页排名一样计算每个句子的重要性得分最后选出得分最高的几个句子。import jieba from sklearn.feature_extraction.text import TfidfVectorizer import numpy as np import networkx as nx def generate_extractive_summary(text, top_n2): 使用基于TextRank思想的提取式摘要生成 # 1. 分句 sentences [s.strip() for s in text.split(。) if len(s.strip()) 5] # 2. 对每个句子进行分词 words_in_sentences [ .join(jieba.cut(sent)) for sent in sentences] # 3. 计算TF-IDF向量 vectorizer TfidfVectorizer() tfidf_matrix vectorizer.fit_transform(words_in_sentences).toarray() # 4. 计算句子相似度矩阵余弦相似度 sim_matrix np.zeros((len(sentences), len(sentences))) for i in range(len(sentences)): for j in range(len(sentences)): if i ! j: # 计算余弦相似度 cos_sim np.dot(tfidf_matrix[i], tfidf_matrix[j]) / (np.linalg.norm(tffidf_matrix[i]) * np.linalg.norm(tfidf_matrix[j]) 1e-8) sim_matrix[i][j] cos_sim # 5. 构建图并计算PageRank nx_graph nx.from_numpy_array(sim_matrix) scores nx.pagerank(nx_graph) # 6. 按得分排序选取top_n个句子 ranked_sentences sorted(((scores[i], i, sentences[i]) for i in range(len(sentences))), reverseTrue) # 7. 按原始顺序输出选中的句子 selected_indices sorted([ranked_sentences[i][1] for i in range(top_n)]) summary 。.join([sentences[idx] for idx in selected_indices]) 。 return summary # 使用示例对BERT分割后的一个段落进行摘要 if __name__ __main__: # 假设segments是BERT分割后的结果 sample_segment segments[1] # 取第二个段落 summary generate_extractive_summary(sample_segment, top_n2) print( 原始段落片段) print(sample_segment[:300] ...) print(\n 生成摘要 ) print(summary)这段代码实现了一个简化版的提取式摘要。在实际应用中你还可以融入更多特征比如句子位置开头结尾的句子通常更重要、是否包含关键词等来提升摘要的质量。最终程序会遍历所有分割好的段落为每个段落生成一小段摘要并将它们组合起来形成整篇文章的“内容大纲”和“要点清单”。5. 总结走完这一整套流程我们再回头看看。这个项目展示的不仅仅是用Python爬虫抓取数据或者调用一个BERT模型那么简单。它更像是一个微型的“信息处理流水线”把散落在网络上的长篇技术信息自动加工成结构化的知识卡片。整个过程跑下来给我的感觉是“高效”和“实用”。对于需要快速阅读大量文献的研究者、需要做竞品分析的产品经理或者只是想高效学习新技术的开发者来说这套思路能节省大量初始的阅读和整理时间。它生成的摘要和大纲虽然还不能完全替代深度阅读但作为预习、复习或者建立知识索引已经非常够用了。当然现在这个展示版本还有很多可以打磨的地方。比如摘要的流畅度和重点把握还能通过更先进的模型如BART、T5等生成式模型来优化爬虫的健壮性需要应对更多网站结构整个流程也可以打包成一个有简单界面的小工具。但它的核心价值已经体现出来了利用现有的AI模型和算法我们完全可以自动化那些重复、繁琐的信息预处理工作把人的时间和精力留给更需要创造力和深度思考的环节。如果你对自然语言处理或自动化工具感兴趣不妨沿着这个方向动手试试把它改造得更加强大易用。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询