python-mini-projects 实战:基于 requests 与 BeautifulSoup 抓取 Medium 文章正文并保存为 TXT
python-mini-projects 实战:基于 requests 与 BeautifulSoup 抓取 Medium 文章正文并保存为 TXT
📅 发布时间:2026/9/21 0:03:19👁 浏览次数:
示例工程【免费下载链接】python-mini-projectsA collection of simple python mini projects to enhance your python skills项目地址https://gitcode.com/gh_mirrors/py/python-mini-projects点击查看免费下载导读本文围绕 python-mini-projects 仓库中的「Scraping Medium Articles」小项目展开讲解如何用 Python 写一个命令行脚本用户输入一篇 Medium 文章的 URL脚本自动抓取该页面 HTML清洗掉标签后提取标题、作者、导语与正文并保存为纯文本文件到本地scraped_articles目录。读完本文你将掌握 requests 抓取网页、BeautifulSoup 解析 DOM、正则清洗文本以及文件自动落盘这一套完整的静态网页抓取流程并能直接在本仓库目录中运行验证。项目定位一条命令把 Medium 文章变成本地 TXTMedium 是全球程序员常用的技术写作平台页面结构稳定、正文语义清晰非常适合作为网页抓取的入门练习对象。该项目的核心目标非常聚焦给定一篇 Medium 文章 URL抓取其纯文本内容并落盘保存。项目入口文档位于 projects/Scraping Medium Articles/README.md核心实现只有一个文件 scraping_medium.py依赖仅两个第三方库非常适合初学者读懂、改跑、再扩展。项目目录结构如下projects/Scraping Medium Articles/ ├── README.md # 项目说明 ├── requirements.txt # 第三方依赖清单 ├── scraping_medium.py # 核心抓取脚本 └── scraped_articles/ # 抓取结果输出目录已含 3 篇示例 ├── One_month_into_the_MLH_Fellowship.txt ├── One_stop_guide_to_Google_Summer_of_Code.txt └── The_Pros_and_Cons_of_Open_Source_Software.txtscraped_articles目录中已经预置了 3 个抓取结果示例文件用于直观展示脚本的输出格式这也是验证脚本是否正常工作的现成参考。环境准备与依赖安装根据 README.md 的 Prerequisites 一节运行前需要满足两个条件安装依赖使用pip安装 requirements.txt 中列出的模块网络连通设备上需要有可用的网络连接因为脚本需要实时访问 Medium 页面。requirements.txt 中固定了两个核心依赖及其版本beautifulsoup44.9.1 requests2.23.0安装命令pip install -r projects/Scraping Medium Articles/requirements.txt说明上述版本号是仓库中锁定的版本若你本机 Python 环境较新pip在安装时可能会自动升级到满足该版本约束的最新兼容版本若遇到依赖冲突可去掉版本号直接pip install requests beautifulsoup4。运行方式像运行普通 Python 文件一样README 明确指出运行该脚本与运行任意 Python 文件无异python projects/Scraping Medium Articles/scraping_medium.py启动后脚本会提示Enter url of a medium article:粘贴一篇 Medium 文章链接并回车脚本随即完成抓取、清洗与保存并在终端打印保存位置例如File saved in directory ./scraped_articles/One_month_into_the_MLH_Fellowship.txt整个交互只有一次输入属于典型的「一次性输入、自动处理」的命令行工具。源码深度解析四步完成一篇文章的抓取虽然脚本只有 70 余行却完整覆盖了网页抓取的四个核心环节。下面按 scraping_medium.py 的代码顺序逐段剖析。1. 定位脚本目录保证输出路径稳定脚本开头有一行容易被忽略的关键代码scraping_medium.py# switching to current running python files directory os.chdir(\\.join(__file__.split(/)[:-1]))它把当前工作目录切换到脚本自身所在目录从而确保后续创建的./scraped_articles输出目录始终位于脚本旁边而不是用户运行命令时所在的随机目录。这样做的好处是无论从哪个路径调用脚本输出位置都是确定且可预期的。2.get_page()URL 校验 页面请求与解析get_page()函数scraping_medium.py负责三个阶段的工作def get_page(): global url url input(Enter url of a medium article: ) # handling possible error if not re.match(rhttps?://medium.com/,url): print(Please enter a valid website, or make sure it is a medium article) sys.exit(1) res requests.get(url) res.raise_for_status() soup BeautifulSoup(res.text, html.parser) return soupURL 合法性校验用正则rhttps?://medium.com/检查用户输入只接受以http://medium.com/或https://medium.com/开头的地址否则打印提示并以sys.exit(1)退出。这一步有效拦截了误输入的非 Medium 链接。发起 HTTP 请求通过requests.get(url)拉取页面随后调用res.raise_for_status()当响应状态码为 4xx/5xx 时该方法会抛出异常避免把错误页面当正文解析。构造解析树用BeautifulSoup(res.text, html.parser)把 HTML 文本解析成可遍历的文档树供后续步骤提取内容。3.purify()正则驱动的 HTML 标签清洗purify()函数scraping_medium.py负责把带有标签的 HTML 片段还原为可读的纯文本def purify(text): rep {br: \n, br/: \n, li: \n} rep dict((re.escape(k), v) for k, v in rep.items()) pattern re.compile(|.join(rep.keys())) text pattern.sub(lambda m: rep[re.escape(m.group(0))], text) text re.sub(\(.*?)\, , text) return text它的处理逻辑分两步特殊标签替换为换行先把br、br/、li这三种标签替换成\n使得换行语义被保留下来。实现上用re.escape对替换键做转义后拼接成正则再通过pattern.sub配合 lambda 完成映射替换避免替换结果被后续正则再次误伤。删除其余所有标签用re.sub(r\(.*?)\, , text)把剩下的所有尖括号标签如p、a、strong等整体移除只保留纯文本内容。这种「先保留换行语义、再删除标签」的两段式清洗是静态页面文本抽取的常用手法比简单粗暴地删除所有标签能得到更接近原文排版的结果。4.collect_text()按 Medium 页面结构组装正文collect_text()scraping_medium.py是整个脚本的信息组织核心它依据 Medium 页面的 DOM 结构规律来提取并拼装内容def collect_text(soup): fin furl: {url}\n\n main (soup.head.title.text).split(|) global title title main[0].strip() fin fTitle: {title.upper()}\n{main[1].strip()} header soup.find_all(h1) j 1 try: fin \n\nINTRODUCTION\n for elem in list(header[j].previous_siblings)[::-1]: fin f\n{purify(str(elem))} except: pass fin f\n\n{header[j].text.upper()} for elem in header[j].next_siblings: if elem.name h1: j1 fin f\n\n{header[j].text.upper()} continue fin f\n{purify(str(elem))} return fin这一段暗含了对 Medium 页面结构的几个假设结合仓库中 scraped_articles 的示例输出可以一一印证标题与作者来源Medium 页面title的格式通常是「文章标题 | 出版物名称」。脚本用split(|)拆分main[0]作为文章标题并转大写main[1]作为作者/出版物署名行拼成Title: xxx与署名两行。示例文件开头的Title: ONE MONTH INTO THE MLH FELLOWSHIP、by Kunal Kushwaha正是这一逻辑的直接产物。导语INTRODUCTION提取取页面中所有h1标签把第二个h1之前的所有兄弟节点反向遍历并清洗作为 INTRODUCTION 段——即文章头部作者信息、阅读时长等元数据。正文分节提取以第二个h1为起点向后遍历兄弟节点遇到新的h1就换行输出该小节标题转大写普通节点则经purify()清洗后追加为正文。Medium 正文中的小标题本身就是h1所以脚本天然地把文章切成多个「大写标题 段落」的小节。示例输出中INTRODUCTION、WEEK 1、WEEK 2等小节标题全部大写、段落之间以空行分隔的排版正是上述组装逻辑的运行结果。5.save_file()自动建目录并按标题命名落盘save_file()scraping_medium.py负责持久化def save_file(fin): if not os.path.exists(./scraped_articles): os.mkdir(./scraped_articles) fname ./scraped_articles/ _.join(title.split()) .txt with open(fname, w, encodingutf8) as outfile: outfile.write(fin) print(fFile saved in directory {fname})若scraped_articles目录不存在则自动创建文件名取自文章标题把标题中的空格替换为下划线_.join(title.split())如One_month_into_the_MLH_Fellowship.txt以utf8编码写入兼容文章中的中文、emoji 等非 ASCII 字符落盘后打印保存路径方便用户确认结果。6. 驱动入口文件末尾的标准入口scraping_medium.py把上述函数串成完整流水线if __name__ __main__: fin collect_text(get_page()) save_file(fin)get_page()返回解析树 →collect_text()组装成纯文本 →save_file()写入磁盘一条主线完成全部抓取任务。输出文件格式规范以仓库自带的 One_month_into_the_MLH_Fellowship.txt 为例输出文件的固定结构为url: https://medium.com/.../slug Title: 文章标题大写 by 作者署名 INTRODUCTION 导语与元信息段落 小节标题大写 小节正文段落 ...即首行保留原始 URL 便于溯源随后是标题与署名INTRODUCTION段收纳文章头部信息之后每个h1小标题独立成节、大写展示。这种「保留来源 结构化分节」的格式让抓取结果既适合直接阅读也方便后续做文本分析、语料库构建等二次加工。边界条件与已知限制基于源码实现根据代码逻辑脚本存在以下客观边界使用时需要留意仅接受https?://medium.com/前缀的 URL正则校验决定了它只能处理 Medium 主域下的文章诸如子域名、自定义域或非 Medium 链接都会被拒绝并退出。强依赖 Medium 的 DOM 结构title的「标题 | 出版物」格式、h1作为正文小标题等假设均针对 Medium 页面设计。若 Medium 调整页面结构INTRODUCTION的提取可能因异常被try/except静默跳过正文分节也可能出现偏差——脚本本身没有对这些分支做显式告警。页面结构假设通过但内容缺失时会静默处理collect_text()中header[j]的索引依赖页面至少存在两个h1极端情况下可能触发IndexError或异常分支。纯文本输出不保留图片与链接purify()会删除所有标签因此文章中的图片、代码块高亮、超链接等富文本信息都会丢失只留下线性文字。这些限制并非缺陷而是小型抓取脚本「够用即可」的典型取舍也为读者预留了改造空间。结合源码的扩展思路在理解现有实现后可以基于同一骨架做如下扩展均不涉及修改仓库仅作为思路参考批量抓取把input()改成从文件或参数列表循环读取多个 URL复用get_page → collect_text → save_file流水线即可增加请求头与限速为requests.get添加User-Agent与time.sleep降低对目标站点的访问压力保留 Markdown 结构在purify()的替换字典中加入h1→#、strong→**等映射直接输出 Markdown编码健壮性对main列表长度做防御性判断避免title格式变化时越界。小结「Scraping Medium Articles」是一个小而完整的爬虫教学样例requests负责取回页面BeautifulSoup负责解析结构正则负责清洗标签最后以 UTF-8 落盘成结构化 TXT。通过本仓库的 README.md、scraping_medium.py 与 scraped_articles 示例三者对照读者可以完整复现「输入 URL → 输出 TXT」的抓取链路并以此为模板迁移到其他静态内容网站的文本抽取任务中。赞分享示例工程【免费下载链接】python-mini-projectsA collection of simple python mini projects to enhance your python skills项目地址https://gitcode.com/gh_mirrors/py/python-mini-projects点击查看免费下载相关推荐python-mini-projects 网页链接抓取实战用 requests BeautifulSoup 提取页面全部链接并保存python mini projects 网页链接抓取实战用 requests BeautifulSoup 提取页面全部链接并保存 本技术指南以 pyth示例工程python-mini-projects 实战用 requests BeautifulSoup 编写 Quote Scraper 名言爬虫并导出 CSVpython mini projects 实战用 requests BeautifulSoup 编写 Quote Scraper 名言爬虫并导出 CSV示例工程python-mini-projects 实战基于 BeautifulSoup 的 moneycontrol 金融新闻多页爬虫python mini projects 实战基于 BeautifulSoup 的 moneycontrol 金融新闻多页爬虫 本文以 python mini示例工程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考