Python采集腾讯新闻实例

发布时间:2026/10/12 12:06:45

Python采集腾讯新闻实例 前言拿一个真实门户站当例子来练手是很有价值的因为门户站会把你在练习站上遇不到的问题一次性摆到面前列表页和详情页要分两步抓、页面里混着广告和推荐位、内容可能由 JavaScript 渲染、站点还会不时改版。但正因为是真实站点这个例子里合规不是可选项而是第一步。有几句必须写在最前面。第一采集新闻类内容涉及著作权把别人的稿件全文抓下来再发布无论技术多简单都不可以本文的例程只演示「取标题、取链接、做摘要研究」这一层面不鼓励也不演示任何形式的全文转载或再分发。第二动手前请自己去看目标站的 robots.txt 与用户协议看它允不允许你抓、允许抓哪些路径、以什么频率抓。第三本文不会给出任何绕过登录墙、付费墙、验证码或风控的做法——遇到需要登录才能看的内容正确结论就是「看不到不抓」而不是想办法进去。还要说明一点门户站页面结构变化频繁很多内容由前端脚本异步加载。所以下面给的解析代码是通用骨架具体到某个 class 名、某种链接形式的过滤规则必须以你当时实际看到的页面为准。任何号称「一份选择器写死就能长期用」的教程都是不诚实的。代码基于 Python 3Python 2.7 已于 2020 年 1 月 1 日停止维护下文一律用 Python 3 写法。一、采集新闻稿的一般流程新闻站的采集几乎都是「两步走」步骤输入输出关键动作列表页频道首页 / 分页 URL一批文章链接 标题过滤掉导航、广告、推荐位详情页单个文章 URL标题 正文段落 时间去广告、去推荐、取正文清洗原始文本规整记录去空白、去干扰行落盘记录列表JSON / CSV显式编码、及时写入第一步的重点是把链接筛干净导航链接、栏目链接、「更多」链接、广告位链接都不能当成文章。常见的过滤思路是看href的形态是否包含文章路径特征、是否以.html结尾而不是去数「第几个 a 标签」。二、合规前置检查要写在第一行把这几件事做成程序入口处的硬性检查比事后补救靠谱读 robots.txturllib.robotparser.RobotFileParser的set_url()→read()→can_fetch(useragent, url)。只有返回True才继续。读不到 robots.txt 时按保守策略当作「不允许」下次再试。如实标明身份User-Agent里写清你的程序名和联系方式不要伪装成浏览器。全局限速任意两次请求之间留间隔time.sleep并且把总请求数设上限。只碰公开内容需要登录、需要付费、robots.txt 明令禁止的路径一律不抓。分清用途做统计、研究、舆情分析这类用途和「把稿件搬到自己的站上」完全是两回事。三、列表页解析只收文章链接用html.parser.HTMLParser写一个「收集所有 a 标签的 href 和文字」的解析器再在外面按规则过滤。这样解析器和站点结构解耦站点改版时大多只需要改过滤规则。注意attrs是「(名字, 值) 二元组」的列表不是字典要dict(attrs)之后再.get(href)。另外feed()之后别忘了close()。四、详情页解析抽正文段落详情页的正文通常是若干p标签。一个朴素但有效的做法是收集所有p里的文字再丢掉过短的行版权声明、推荐语、关注按钮文字往往很短。这个规则不完美——有的站点用div而不是p装正文——但它是你能在不了解站点内部结构时最先用上的启发式规则。真要做得稳得针对站点实际结构定制并接受「改版就失效」这个事实。实战通用骨架 可验证的解析器下面这段代码可以直接跑但把LIST_URL换成你自己确认过 robots 允许的页面。解析逻辑我同时用一段本地 HTML 字符串做了自检这样即使不联网你也能看到解析器的工作结果。# 适用于 Python 3.8import timeimport urllib.errorimport urllib.parseimport urllib.requestimport urllib.robotparserfrom html.parser import HTMLParserUA news-list-reader/0.1 (contact: feedexample.com)DELAY 1.0 # 任意两次请求之间的间隔秒MAX_ARTICLES 5 # 本次采集的文章数上限class ListParser(HTMLParser):收集页面里所有 a 标签的 (href, 文字)。def __init__(self):super().__init__()self.links []self._href Noneself._buf []def handle_starttag(self, tag, attrs):if tag a:href dict(attrs).get(href)if href:self._href hrefself._buf []def handle_data(self, data):if self._href is not None:self._buf.append(data)def handle_endtag(self, tag):if tag a and self._href is not None:self.links.append((self._href, .join(self._buf).strip()))self._href Noneclass ParagraphCollector(HTMLParser):收集所有 p 标签里的文字当作正文段落。def __init__(self, min_len10):super().__init__()self.min_len min_lenself._in_p Falseself._buf []self.paragraphs []def handle_starttag(self, tag, attrs):if tag p:self._in_p Trueself._buf []def handle_data(self, data):if self._in_p:self._buf.append(data)def handle_endtag(self, tag):if tag p and self._in_p:self._in_p Falsetext .join(self._buf).strip()if len(text) self.min_len:self.paragraphs.append(text)def fetch_text(url, timeout15):req urllib.request.Request(url, headers{User-Agent: UA})with urllib.request.urlopen(req, timeouttimeout) as resp:charset resp.headers.get_content_charset() or utf-8return resp.read().decode(charset, errorsreplace)def robots_allowed(url):parts urllib.parse.urlsplit(url)robots_url urllib.parse.urlunsplit((parts.scheme, parts.netloc, /robots.txt, , ))parser urllib.robotparser.RobotFileParser()parser.set_url(robots_url)try:parser.read()except Exception:return False # 读不到就当作不允许return parser.can_fetch(UA, url)def is_article_link(href):过滤规则要按目标站实际结构写这里只做最基本的形态判断。if href.startswith((javascript:, #, mailto:)):return Falsepath urllib.parse.urlsplit(href).pathreturn path.endswith(.html) or /article/ in pathdef collect_list(list_url, limitMAX_ARTICLES):parser ListParser()parser.feed(fetch_text(list_url))parser.close()articles []seen set()for href, title in parser.links:if not is_article_link(href):continueabsolute urllib.parse.urljoin(list_url, href)if absolute in seen:continueseen.add(absolute)articles.append((absolute, title))if len(articles) limit:breakreturn articlesdef collect_article(url):time.sleep(DELAY) # 进详情页之前先限速parser ParagraphCollector()parser.feed(fetch_text(url))parser.close()return parser.paragraphsdef self_test():不联网用本地 HTML 验证两个解析器。html div classnava href/首页/aa href/sports/体育/a/divullia href/news/20260101A001.html某地发布年度经济数据/a/lilia hrefjavascript:void(0)更多/a/lilia href/news/20260101A002.html行业论坛昨日举行/a/li/ullp ListParser()lp.feed(html)lp.close()picked [(urllib.parse.urljoin(https://news.example.com/, h), t)for h, t in lp.linksif is_article_link(h)]print(列表页筛出:, picked)detail p第一段正文长度足够。/pp短/pp第二段正文长度也够。/pap ParagraphCollector()ap.feed(detail)ap.close()print(正文段落:, ap.paragraphs)def main(list_url):if not robots_allowed(list_url):print(robots.txt 不允许抓取退出)returnfor url, title in collect_list(list_url):try:paragraphs collect_article(url)except urllib.error.HTTPError as exc:print(跳过, url, exc.code)continueprint(title, -, len(paragraphs), 段)if __name__ __main__:self_test()# 确认 robots.txt 允许后再取消下一行的注释# main(https://example.com/news/)self_test()那段是不联网的跑起来会打印列表页筛出: [(https://news.example.com/news/20260101A001.html, 某地发布年度经济数据), (https://news.example.com/news/20260101A002.html, 行业论坛昨日举行)]正文段落: [第一段正文长度足够。, 第二段正文长度也够。]注意筛选结果里没有「首页」「体育」「更多」——它们分别被is_article_link的路径判断和javascript:前缀挡掉了。这正是列表页解析要做的事把干扰链接拦在门外。常见坑点1. 不检查 robots.txt 就开始抓❌ 直接对着频道首页循环翻页。 ✅ 入口处先RobotFileParser判断不允许就停。2. 把整站所有链接都当文章抓❌ 见到a就入队结果爬了一堆导航页和广告落地页。 ✅ 用路径特征过滤并额外维护seen集合去重。3. 用伪装 UA 冒充浏览器❌ 抄一个浏览器 UA 字符串帖上去。 ✅ 写清自己的程序名和联系方式便于对方在需要时联系你。4. 以为文档就是完整 DOM❌urlopen拿到的 HTML 里找不到内容就以为「抓不到」。 ✅ 很多内容是脚本异步加载的。先确认这条内容有没有合规的静态接口不要去逆向破解签名或绕过风控。5. 把「需要登录才能看」的内容当成技术挑战❌ 研究怎么携带登录态进付费内容区。 ✅ 结论很明确那部分内容不抓。本文不提供任何绕过登录墙或付费墙的做法。6. 去掉间隔猛翻页❌ 把time.sleep删掉靠高并发「提速」。 ✅ 保留间隔和总数上限。对真实站点礼貌和合规永远排在速度前面。7. 把抓到的全文直接再发布❌ 抓完就贴到自己的站点或公众号。 ✅ 新闻内容有著作权。研究、统计、摘要引用与全文再分发是两回事别越界。8. 硬编码一次选择器就不管了❌ 把某天看到的 class 名写死然后半年不看。 ✅ 解析规则要能容错——取不到字段时留空并记日志站点改版时按新结构更新。总结阶段做什么合规红线前置读 robots.txt、定 UA、定频率robots 不允许就不抓列表页收链接、按形态过滤、去重不抓导航/广告也不「碰运气」扩大范围详情页抽标题与正文段落不碰登录墙/付费墙后的内容清洗去短行、去空白不改动原意地做摘要落盘显式 UTF-8 写入不全文转载再分发采集一个真实门户站技术上的骨架和采练习站没有本质区别请求、解析、清洗、落盘。真正的差别在约束——你有义务先问清楚「能不能抓」再决定「怎么抓」。把合规检查写成代码的第一行把限速写进循环把「不碰登录墙和付费墙」当成默认规则这样的采集才做得长久。
延伸阅读

更多相关文章

2026/10/12 12:06:45

单级式光伏并网仿真:MPPT与并网控制耦合及参数整定全攻略

1. 为什么执意选单级式拓扑:省掉一级变换带来的控制难题单级式光伏并网系统,简单说就是光伏阵列直接接一台逆变器,再通过滤波器并入电网,中间没有DC-DC升压环节。相比两级式拓扑(前级Boost调压、后级逆变并网&#xff…

2026/10/12 12:06:45

PYNQ PS定时器中断实战:从UIO到内核模块的微秒级调度

1. 从裸机到异构:为什么PS定时器中断值得单独拎出来讲做过嵌入式开发的人都有一个共识:中断这东西,入门容易精通难。尤其在异构平台上,比如带有ARM处理器和可编程逻辑的SoC架构,中断的分配、路由、响应路径比传统单片机…

2026/10/12 12:56:54

ABAP ALV报表自定义按钮执行完后隐藏的两种实现方案与实战

做ABAP开发的,十个ALV报表里少说有七八个要放自定义按钮。业务顾问的需求往往很简单——“加一个按钮,点了执行一下,执行完了就别再给用户点了”。比如生成对账单、执行批量过账、触发一次数据同步,点过一次如果还能再点&#xff…

2026/10/12 12:56:54

LSTM财务因子选股模型实战:数据防泄漏与回测验证全解析

简介:面向高校计算机、金融科技等相关专业学生的Python毕业设计/课程设计高分源码,基于LSTM神经网络构建财务因子预测选股模型,同时附带BP网络与MACD/RSI技术指标实现,可完成从财务数据处理、模型训练到选股信号输出的完整流程。压…

2026/10/12 12:56:54

ALV自定义按钮执行后自动隐藏:SALV与经典ALV完整实现

做 ABAP 开发的兄弟应该都遇到过这种场景:ALV 报表界面上放了一个自定义按钮,比如"执行特殊处理""锁定数据""补充审批"之类。用户点一次,业务逻辑跑完了,这个按钮也完成了它的历史使命,…

2026/10/12 12:56:54

前端开发者转型AI Agent:基于Mastra与TypeScript的实战指南

说实话,这半年被问得最多的一个问题,不是某个组件怎么写,而是“前端现在还能不能上车AI”。每次听到这话我都想反问一句:你手上掌握的TypeScript、你对组件状态的管理、你对接口数据的处理,这些能力搬到Agent开发里&am…

2026/10/12 12:51:52

FFmpeg集成AV1编码器:libaom-av1完整编译指南

这几年做视频分发的人几乎都绕不开AV1这个格式。省带宽、压画质、跨平台播放兼容性逐步成熟,都是它的优势,但真到自己搭建编码服务时,第一步就卡在编译上:FFmpeg默认不带AV1编码器,想用libaom-av1必须自己把库编进来。…

2026/10/11 0:02:13

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/12 12:01:26

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/12 12:54:07

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/12 0:04:22

绝缘子缺陷检测数据集清洗与工业级训练实战指南

简介:本资源是面向电力AI研发人员、工业视觉工程师及智能巡检系统开发者的绝缘子缺陷检测专用YOLO格式数据集,解决无人机航拍场景下绝缘子破损、污闪、积雪等9类典型缺陷的精准识别与定位难题。数据集共2139张真实巡检图像(含训练/验证/测试集…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑