python爬虫使用正则爬取网站的实现
前言用正则表达式从网页里提取内容是很多人接触爬虫的第一步拿到 HTML 源码用re.findall把链接、标题、价格抠出来。这条路学习成本低但也最容易被用歪——既容易写出脆弱的模式也容易忽视抓取的分寸。本文要先把两件事说清楚。第一正则不是解析 HTML 的正确工具。HTML 不是正则语言标签可能嵌套、属性顺序可变、还有注释和脚本正则只在「结构简单且稳定」的片段上可靠。第二抓取要合规遵守目标站点的robots.txt、如实表明自己的 User-Agent、控制请求频率、不绕过登录或付费限制、不做高并发把对方打挂。反爬机制的存在有它的原因本文只讲「怎么合规地抓」不讲任何绕过手段。下面用一个最小可运行的例子演示「先问 robots、再取页面、用正则提取链接、限速」的完整闭环。示例基于 Python 3.8。一、Python 3 的抓取工具链Python 2 时代流行urllib2这个模块在 Python 3 里已经不存在了它的功能被合并进urllib.request。Python 2.7 已于 2020 年 1 月 1 日停止维护旧教程里的urllib2.urlopen(url)写法一律不能再用本文全部采用 Python 3 的路径用途Python 3 模块说明发起请求urllib.requestRequest/urlopen解析相对链接urllib.parseurljoin(base, link)读取抓取规则urllib.robotparserRobotFileParser正则匹配re只用于结构稳定的片段先关心合规urllib.robotparser.RobotFileParser能读站点根目录的robots.txt用can_fetch(useragent, url)判断某个 URL 允不允许抓。注意它判断的是「给定 UA 下能不能访问」所以 UA 字符串要和实际请求头里的一致。二、完整示例合规地取一个页面的链接# 适用于 Python 3.8import reimport timeimport urllib.requestimport urllib.robotparserfrom urllib.parse import urljoinBASE https://example.com/UA MyCrawler/1.0 (https://example.com/about-bot)# 只匹配 href 属性里的取值单双引号都接受LINK_RE re.compile(rhref[]([^])[], re.IGNORECASE)def allowed(url):查 robots.txt判断当前 UA 是否可以抓取 url。rp urllib.robotparser.RobotFileParser()rp.set_url(urljoin(url, /robots.txt))try:rp.read()except OSError:# 读不到规则时保守处理不抓return Falsereturn rp.can_fetch(UA, url)def fetch(url):发起 GET 请求按响应声明的编码解码成文本。req urllib.request.Request(url, headers{User-Agent: UA})with urllib.request.urlopen(req, timeout10) as resp:charset resp.headers.get_content_charset() or utf-8return resp.read().decode(charset, errorsreplace)def extract_links(html, base):用正则找出所有 href并把相对地址补成绝对地址。hrefs LINK_RE.findall(html)return [urljoin(base, h) for h in hrefs]if __name__ __main__:url BASEif allowed(url):html fetch(url)for link in extract_links(html, url):print(link)time.sleep(1) # 每次请求之间歇一秒控制频率else:print(robots.txt 不允许抓取, url)模式rhref[]([^])[]用三重单引号包住是为了让里面的和都不需要转义。[^]是「一个及以上非引号字符」正好卡住属性值re.IGNORECASE让HREF也能匹配。urljoin(base, href)会处理三种情况绝对地址原样返回/path补成站点根下的绝对地址page.html补成同级绝对地址。少了这一步正则抠出来的往往是一堆相对路径后续没法直接用。三、正则 vs 结构化解析只做「捞链接、抓数字」这类扁平任务正则是够用的一旦结构变复杂就该换工具场景正则rehtml.parser.HTMLParser提取固定属性的值合适模式短也可以但要写子类回调嵌套结构、多层级容易失手按标签层次处理稳容错性缺闭合标签差HTMLParser 也不完美但更可控学习成本低中结论正则用来处理局部、扁平的片段整页结构交给html.parser或专门库。把整页 HTML 塞进一个正则里做「万能匹配」是最常见的失败来源。四、看一眼 robots.txt 长什么样robots.txt是放在站点根目录的一行行规则告诉爬虫「哪些路径可以抓、抓的间隔多少」User-agent: *Disallow: /admin/Disallow: /tmp/Crawl-delay: 5User-agent: MyCrawlerDisallow:大意是对大多数爬虫/admin/和/tmp/不许进每次请求之间至少隔 5 秒。而针对MyCrawler的单条规则写了空的Disallow:表示对这一个 UA 放行全部。RobotFileParser读进来后can_fetch(MyCrawler/1.0, https://example.com/admin/x)会给出是否放行的判断——它匹配的是 UA 的前缀所以传给can_fetch的字符串要与请求头里保持一致。需要留意的是Crawl-delay不是所有解析器都会自动执行实践中仍应自己在代码里time.sleep。五、真的需要解析结构时换用 HTMLParser官方标准库自带html.parser.HTMLParser用回调的方式按标签取数据比正则稳# 适用于 Python 3.8from html.parser import HTMLParserclass LinkGrabber(HTMLParser):def __init__(self):super().__init__()self.links []def handle_starttag(self, tag, attrs):if tag ! a:returnfor name, value in attrs:if name href and value:self.links.append(value)page a href/aA/aa classx href/bB/ag LinkGrabber()g.feed(page)print(g.links) # [/a, /b]HTMLParser会把标签名转成小写、把属性解析成(名字, 值)的列表正好绕开了「属性顺序可变、单双引号混用」这些让正则头疼的问题。代价是要写子类、处理回调。什么时候切换当你的正则开始出现「一层套不进去就加一个.*?」的时候就该换了。常见坑点❌ 把.*用在跨行的 HTML 上结果只匹配到第一行还以为页面没内容。✅ 默认.不匹配换行跨行提取要么加re.DOTALL要么用[\s\S]*?这类显式包含换行的写法。❌ 用re.findall(rhref(.*), html)这类贪心模式一次把从第一个href到行尾最后引号的内容全吞了。✅ 用[^]代替.*把「不能是引号」写进字符集天然截断在属性值末尾。❌ 请求时不写 User-Agent用库的默认值被对方按「未知爬虫」拦掉。✅ 如实填写能标识自己的 UA通常带上用途或联系方式不要伪装成浏览器去骗过校验。❌ 无视robots.txt直接按链接列表批量抓取。✅ 先用RobotFileParser.can_fetch(UA, url)判断只抓允许的部分读不到规则时按不放行处理。❌ 在循环里不 sleep 地连续请求短时间把对方压出高负载。✅ 请求之间加time.sleep串行访问控制并发量给对方留出余量。❌ 直接对resp.read()返回的 bytes 用str模式匹配报TypeError: cannot use a string pattern on a bytes-like object。✅ 先decode成str编码优先取响应头声明的get_content_charset()拿不到再退回utf-8。❌ 抠出href后直接当 URL 用跳转时才发现是/about这样的相对路径。✅ 用urllib.parse.urljoin(base, href)归一成绝对地址再处理。❌ 用正则解析嵌套的div结构页面一改样式就整段失配。✅ 结构复杂的部分改用html.parser.HTMLParser或专门的解析库正则只负责最外层、最稳定的模式。总结环节做法关键点合规检查RobotFileParser.can_fetch读不到规则就不抓发起请求urllib.request 自定义 UA如实标识别伪装解码decode(charset, errorsreplace)正则要在str上跑提取re.findall[^]用字符集截断别用.*归一urljoin相对路径转绝对限速time.sleep串行、低频、不压垮对方用正则写爬虫本质是在做「文本提取」而不是「DOM 解析」所以要挑结构简单、格式稳定的部分下手同时对抓取行为负责。合规、低频、明确身份这三条比任何技巧都重要。

相关新闻

图像超分辨入门:三种经典插值算法原理与实战对比

图像超分辨入门:三种经典插值算法原理与实战对比

从大一开始接触数字图像处理,我就发现“图像超分辨”这个名字有点劝退。很多人一上来就把它想成需要显卡、需要庞大训练集、需要跑上几天才能完成的深度学习任务。但实际上,在深度学习普及之前,甚至到现在很多工程场景里,基于插值…

2026/10/15 13:21:53 阅读更多 →
教育专用大模型:从问答工具到教学认知协作者

教育专用大模型:从问答工具到教学认知协作者

简介:本资源是之江实验室联合中国教育科学研究院发布的《重构教育图景:教育专用大模型研究报告(简版)》,面向教育技术研究者、AI教育产品开发者、K12学校信息化负责人及教育政策制定者,系统回应教育大模型‘…

2026/10/15 13:21:53 阅读更多 →
FFmpeg音频重采样与AAC编码优化实战指南

FFmpeg音频重采样与AAC编码优化实战指南

1. 音频重采样技术背景解析在数字音频处理领域,重采样(Resampling)是一项基础但至关重要的技术。简单来说,它就像把不同尺寸的图片进行缩放转换,只不过我们处理的对象是音频数据。当我们需要将音频从48kHz降到44.1kHz&…

2026/10/15 13:21:52 阅读更多 →

最新新闻

SQLite FTS5 context-mode:中文全文检索的BM25实战范式

SQLite FTS5 context-mode:中文全文检索的BM25实战范式

1. “context-mode”不是功能开关,而是SQLite FTS5全文检索的底层执行范式你在网上搜“context-mode”,大概率会一头雾水——它既不是某个知名开源项目的官方术语,也不在SQLite官方文档的索引页里高亮出现。我第一次在RuoYi-Vue-Pro的PR评论区…

2026/10/15 14:03:58 阅读更多 →
C++代理模式详解:从基础到高级应用

C++代理模式详解:从基础到高级应用

1. 代理模式基础概念回顾在正式探讨代理模式的变体之前,我们需要先明确经典代理模式的核心机制。代理模式属于结构型设计模式,其主要目的是为其他对象提供一种代理以控制对这个对象的访问。这种模式在C中尤为常见,因为它能很好地解决直接访问…

2026/10/15 14:03:58 阅读更多 →
Java IO体系深度解析:BIO、NIO与AIO对比与实践

Java IO体系深度解析:BIO、NIO与AIO对比与实践

1. Java IO体系全景解析Java IO体系是每个Java开发者必须掌握的核心基础,也是面试中高频出现的"硬骨头"。我见过太多候选人能说出BIO/NIO/AIO这几个缩写,却讲不清底层机制和适用场景。今天我们就从操作系统层面开始,彻底拆解这套体…

2026/10/15 14:03:58 阅读更多 →
2025最新Java面试题精讲:从Tomcat到Shiro的原理链路串讲

2025最新Java面试题精讲:从Tomcat到Shiro的原理链路串讲

简介:面向Java后端开发者与2025年求职者,整理的高频面试题文档,围绕Java核心高频考点系统梳理了Tomcat运行原理、Spring IOC/DI与AOP、JVM运行机制、包装类与基本数据类型区别、Shiro权限标签、Servlet生命周期以及Java作用域七个主题展开&am…

2026/10/15 14:03:58 阅读更多 →
前端社招面试复盘:从基础原理到性能优化与工程化实战

前端社招面试复盘:从基础原理到性能优化与工程化实战

前阵子刚面完一个前端工程师的社招岗位,趁着记忆还热乎,把整场面试里涉及的知识点、我的回答思路、答得不好的地方,以及事后复盘下来的改进方案,全部梳理了一遍。这篇文章我先把公司信息隐掉,只保留岗位本身和考核内容…

2026/10/15 14:03:58 阅读更多 →
大型语言模型全解读:转换器、预训练、微调与实战避坑

大型语言模型全解读:转换器、预训练、微调与实战避坑

简介:这是一份面向自然语言处理初学者与大模型应用开发者的全景式大型语言模型解读PDF,内容覆盖LLM定义、Transformer架构、编码器-解码器结构、自注意力机制与单词嵌入原理,并延伸到预训练、微调、零样本和少样本学习等关键环节。正文按定义…

2026/10/15 14:02:53 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 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/15 0:14:36 阅读更多 →
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/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练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/15 9:49:14 阅读更多 →