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 写入不全文转载再分发采集一个真实门户站技术上的骨架和采练习站没有本质区别请求、解析、清洗、落盘。真正的差别在约束——你有义务先问清楚「能不能抓」再决定「怎么抓」。把合规检查写成代码的第一行把限速写进循环把「不碰登录墙和付费墙」当成默认规则这样的采集才做得长久。

相关新闻

SpringBoot+小程序毕设选题:新能源汽车4S店试驾平台全指南

SpringBoot+小程序毕设选题:新能源汽车4S店试驾平台全指南

1. 这个选题到底值不值得做——先替你把关先说结论:如果你正愁毕业设计选什么题,基于SpringBoot的新能源汽车4S店试驾平台小程序这个方向,我能给的评价是——稳妥、有亮点、答辩容易过,而且做出来的东西看起来像个“完整产品”&am…

2026/10/12 12:05:07 阅读更多 →
IDEA构建Spring Boot项目部署生产环境全流程与避坑指南

IDEA构建Spring Boot项目部署生产环境全流程与避坑指南

1. 从一次真实的部署翻车说起上个月帮一个朋友排查线上问题,场景很典型:他在本地用 IDEA 跑得好好的 Spring Boot 服务,打成 jar 包往服务器上一扔,java -jar一执行,日志刷了两屏就停了,接口全部 502。他第…

2026/10/12 12:05:07 阅读更多 →
Empryo 复合工具全解析:一行指令搞定重命名、移动与重构

Empryo 复合工具全解析:一行指令搞定重命名、移动与重构

【免费下载链接】Empryo AI coding harness for desktop, terminal and CI. Maps your repo, edits code by symbol through AST and LSP, then runs your checks. Any model or the plan you already pay for. Get it at https://empryo.com 项目地址: https://git…

2026/10/12 12:05:07 阅读更多 →

最新新闻

LCA最近公共祖先算法详解:倍增法、Tarjan与树链剖分

LCA最近公共祖先算法详解:倍增法、Tarjan与树链剖分

1. 从一道面试题说起:为什么LCA值得花时间搞透第一次接触LCA是在刷题的时候,题目很直白:给一棵树,多次询问两个节点的最近公共祖先。当时我的第一反应是暴力——两个节点分别往上走,标记走过的路径,第一个相…

2026/10/12 12:59:08 阅读更多 →
Python学习第三阶段重点:函数、数据结构、文件与面向对象

Python学习第三阶段重点:函数、数据结构、文件与面向对象

上个星期我收到一条私信,大意是:跟着Python-100天从新手到大师这个学习计划走到第三周,前面的变量、循环、字符串都能看懂,但一进入新内容就觉得吃力。我回了一句:恭喜,你正处在整个计划最关键的转折点。今…

2026/10/12 12:59:08 阅读更多 →
Python多阶段建模预测NBA总冠军:稳定性特征与贝叶斯校准实战

Python多阶段建模预测NBA总冠军:稳定性特征与贝叶斯校准实战

简介:本资源是一个面向Python数据科学初学者与体育数据分析爱好者的NBA总冠军预测实战项目,聚焦机器学习在体育赛事结果预测中的全流程应用。压缩包共131个文件,含113个CSV历史比赛与球员统计原始数据(如2016–2018赛季常规赛、球…

2026/10/12 12:59:08 阅读更多 →
收藏等于学会吗?用数据统计与即时消化计划终结知识囤积

收藏等于学会吗?用数据统计与即时消化计划终结知识囤积

打开收藏夹那天,我算了笔账,然后把囤了三年的“精神资产”删掉了七成。先交代一下背景,我算是那种典型的“数字囤积狂”。浏览器书签攒了2000多条,各平台收藏夹里躺着3000多篇“以后会看”的文章,网盘里存了上百本PDF和…

2026/10/12 12:59:08 阅读更多 →
VSCode插件开发:根据文件路径一键跳转到对应文件的实现方案与TaoToken配置

VSCode插件开发:根据文件路径一键跳转到对应文件的实现方案与TaoToken配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 12:59:08 阅读更多 →
协同过滤图书推荐系统实战:Django+MySQL构建基于商品的推荐引擎

协同过滤图书推荐系统实战:Django+MySQL构建基于商品的推荐引擎

简介:基于Python Django框架的图书推荐系统完整项目,后端采用基于物品的协同过滤算法(Item-based CF),依托豆瓣图书与评分数据集,结合Mysql存储,实现从用户登录、书目管理到推荐结果展示的完整流…

2026/10/12 12:58:07 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →