:基于 requests 與 BeautifulSoup 抓取 Medium 文章正文并保存為 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 倉庫中的「Scraping Medium Articles」小項目展開講解如何用 Python 寫一個命令行腳本用戶輸入一篇 Medium 文章的 URL腳本自動抓取該頁面 HTML清洗掉標簽后提取標題、作者、導語與正文并保存為純文本文件到本地scraped_articles目錄。讀完本文你將掌握 requests 抓取網(wǎng)頁、BeautifulSoup 解析 DOM、正則清洗文本以及文件自動落盤這一套完整的靜態(tài)網(wǎng)頁抓取流程并能直接在本倉庫目錄中運行驗證。項目定位一條命令把 Medium 文章變成本地 TXTMedium 是全球程序員常用的技術(shù)寫作平臺頁面結(jié)構(gòu)穩(wěn)定、正文語義清晰非常適合作為網(wǎng)頁抓取的入門練習對象。該項目的核心目標非常聚焦給定一篇 Medium 文章 URL抓取其純文本內(nèi)容并落盤保存。項目入口文檔位于 projects/Scraping Medium Articles/README.md核心實現(xiàn)只有一個文件 scraping_medium.py依賴僅兩個第三方庫非常適合初學者讀懂、改跑、再擴展。項目目錄結(jié)構(gòu)如下projects/Scraping Medium Articles/ ├── README.md # 項目說明 ├── requirements.txt # 第三方依賴清單 ├── scraping_medium.py # 核心抓取腳本 └── scraped_articles/ # 抓取結(jié)果輸出目錄已含 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目錄中已經(jīng)預置了 3 個抓取結(jié)果示例文件用于直觀展示腳本的輸出格式這也是驗證腳本是否正常工作的現(xiàn)成參考。環(huán)境準備與依賴安裝根據(jù) README.md 的 Prerequisites 一節(jié)運行前需要滿足兩個條件安裝依賴使用pip安裝 requirements.txt 中列出的模塊網(wǎng)絡(luò)連通設(shè)備上需要有可用的網(wǎng)絡(luò)連接因為腳本需要實時訪問 Medium 頁面。requirements.txt 中固定了兩個核心依賴及其版本beautifulsoup44.9.1 requests2.23.0安裝命令pip install -r projects/Scraping Medium Articles/requirements.txt說明上述版本號是倉庫中鎖定的版本若你本機 Python 環(huán)境較新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 余行卻完整覆蓋了網(wǎng)頁抓取的四個核心環(huán)節(jié)。下面按 scraping_medium.py 的代碼順序逐段剖析。1. 定位腳本目錄保證輸出路徑穩(wěn)定腳本開頭有一行容易被忽略的關(guān)鍵代碼scraping_medium.py# switching to current running python files directory os.chdir(\\.join(__file__.split(/)[:-1]))它把當前工作目錄切換到腳本自身所在目錄從而確保后續(xù)創(chuàng)建的./scraped_articles輸出目錄始終位于腳本旁邊而不是用戶運行命令時所在的隨機目錄。這樣做的好處是無論從哪個路徑調(diào)用腳本輸出位置都是確定且可預期的。2.get_page()URL 校驗 頁面請求與解析get_page()函數(shù)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 鏈接。發(fā)起 HTTP 請求通過requests.get(url)拉取頁面隨后調(diào)用res.raise_for_status()當響應狀態(tài)碼為 4xx/5xx 時該方法會拋出異常避免把錯誤頁面當正文解析。構(gòu)造解析樹用BeautifulSoup(res.text, html.parser)把 HTML 文本解析成可遍歷的文檔樹供后續(xù)步驟提取內(nèi)容。3.purify()正則驅(qū)動的 HTML 標簽清洗purify()函數(shù)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使得換行語義被保留下來。實現(xiàn)上用re.escape對替換鍵做轉(zhuǎn)義后拼接成正則再通過pattern.sub配合 lambda 完成映射替換避免替換結(jié)果被后續(xù)正則再次誤傷。刪除其余所有標簽用re.sub(r\(.*?)\, , text)把剩下的所有尖括號標簽如p、a、strong等整體移除只保留純文本內(nèi)容。這種「先保留換行語義、再刪除標簽」的兩段式清洗是靜態(tài)頁面文本抽取的常用手法比簡單粗暴地刪除所有標簽能得到更接近原文排版的結(jié)果。4.collect_text()按 Medium 頁面結(jié)構(gòu)組裝正文collect_text()scraping_medium.py是整個腳本的信息組織核心它依據(jù) Medium 頁面的 DOM 結(jié)構(gòu)規(guī)律來提取并拼裝內(nèi)容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 頁面結(jié)構(gòu)的幾個假設(shè)結(jié)合倉庫中 scraped_articles 的示例輸出可以一一印證標題與作者來源Medium 頁面title的格式通常是「文章標題 | 出版物名稱」。腳本用split(|)拆分main[0]作為文章標題并轉(zhuǎn)大寫main[1]作為作者/出版物署名行拼成Title: xxx與署名兩行。示例文件開頭的Title: ONE MONTH INTO THE MLH FELLOWSHIP、by Kunal Kushwaha正是這一邏輯的直接產(chǎn)物。導語INTRODUCTION提取取頁面中所有h1標簽把第二個h1之前的所有兄弟節(jié)點反向遍歷并清洗作為 INTRODUCTION 段——即文章頭部作者信息、閱讀時長等元數(shù)據(jù)。正文分節(jié)提取以第二個h1為起點向后遍歷兄弟節(jié)點遇到新的h1就換行輸出該小節(jié)標題轉(zhuǎn)大寫普通節(jié)點則經(jīng)purify()清洗后追加為正文。Medium 正文中的小標題本身就是h1所以腳本天然地把文章切成多個「大寫標題 段落」的小節(jié)。示例輸出中INTRODUCTION、WEEK 1、WEEK 2等小節(jié)標題全部大寫、段落之間以空行分隔的排版正是上述組裝邏輯的運行結(jié)果。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目錄不存在則自動創(chuàng)建文件名取自文章標題把標題中的空格替換為下劃線_.join(title.split())如One_month_into_the_MLH_Fellowship.txt以utf8編碼寫入兼容文章中的中文、emoji 等非 ASCII 字符落盤后打印保存路徑方便用戶確認結(jié)果。6. 驅(qū)動入口文件末尾的標準入口scraping_medium.py把上述函數(shù)串成完整流水線if __name__ __main__: fin collect_text(get_page()) save_file(fin)get_page()返回解析樹 →collect_text()組裝成純文本 →save_file()寫入磁盤一條主線完成全部抓取任務(wù)。輸出文件格式規(guī)范以倉庫自帶的 One_month_into_the_MLH_Fellowship.txt 為例輸出文件的固定結(jié)構(gòu)為url: https://medium.com/.../slug Title: 文章標題大寫 by 作者署名 INTRODUCTION 導語與元信息段落 小節(jié)標題大寫 小節(jié)正文段落 ...即首行保留原始 URL 便于溯源隨后是標題與署名INTRODUCTION段收納文章頭部信息之后每個h1小標題獨立成節(jié)、大寫展示。這種「保留來源 結(jié)構(gòu)化分節(jié)」的格式讓抓取結(jié)果既適合直接閱讀也方便后續(xù)做文本分析、語料庫構(gòu)建等二次加工。邊界條件與已知限制基于源碼實現(xiàn)根據(jù)代碼邏輯腳本存在以下客觀邊界使用時需要留意僅接受https?://medium.com/前綴的 URL正則校驗決定了它只能處理 Medium 主域下的文章諸如子域名、自定義域或非 Medium 鏈接都會被拒絕并退出。強依賴 Medium 的 DOM 結(jié)構(gòu)title的「標題 | 出版物」格式、h1作為正文小標題等假設(shè)均針對 Medium 頁面設(shè)計。若 Medium 調(diào)整頁面結(jié)構(gòu)INTRODUCTION的提取可能因異常被try/except靜默跳過正文分節(jié)也可能出現(xiàn)偏差——腳本本身沒有對這些分支做顯式告警。頁面結(jié)構(gòu)假設(shè)通過但內(nèi)容缺失時會靜默處理collect_text()中header[j]的索引依賴頁面至少存在兩個h1極端情況下可能觸發(fā)IndexError或異常分支。純文本輸出不保留圖片與鏈接purify()會刪除所有標簽因此文章中的圖片、代碼塊高亮、超鏈接等富文本信息都會丟失只留下線性文字。這些限制并非缺陷而是小型抓取腳本「夠用即可」的典型取舍也為讀者預留了改造空間。結(jié)合源碼的擴展思路在理解現(xiàn)有實現(xiàn)后可以基于同一骨架做如下擴展均不涉及修改倉庫僅作為思路參考批量抓取把input()改成從文件或參數(shù)列表循環(huán)讀取多個 URL復用get_page → collect_text → save_file流水線即可增加請求頭與限速為requests.get添加User-Agent與time.sleep降低對目標站點的訪問壓力保留 Markdown 結(jié)構(gòu)在purify()的替換字典中加入h1→#、strong→**等映射直接輸出 Markdown編碼健壯性對main列表長度做防御性判斷避免title格式變化時越界。小結(jié)「Scraping Medium Articles」是一個小而完整的爬蟲教學樣例requests負責取回頁面BeautifulSoup負責解析結(jié)構(gòu)正則負責清洗標簽最后以 UTF-8 落盤成結(jié)構(gòu)化 TXT。通過本倉庫的 README.md、scraping_medium.py 與 scraped_articles 示例三者對照讀者可以完整復現(xiàn)「輸入 URL → 輸出 TXT」的抓取鏈路并以此為模板遷移到其他靜態(tài)內(nèi)容網(wǎng)站的文本抽取任務(wù)中。贊分享示例工程【免費下載鏈接】python-mini-projectsA collection of simple python mini projects to enhance your python skills項目地址https://gitcode.com/gh_mirrors/py/python-mini-projects點擊查看免費下載相關(guān)推薦python-mini-projects 網(wǎng)頁鏈接抓取實戰(zhàn)用 requests BeautifulSoup 提取頁面全部鏈接并保存python mini projects 網(wǎng)頁鏈接抓取實戰(zhàn)用 requests BeautifulSoup 提取頁面全部鏈接并保存 本技術(shù)指南以 pyth示例工程python-mini-projects 實戰(zhàn)用 requests BeautifulSoup 編寫 Quote Scraper 名言爬蟲并導出 CSVpython mini projects 實戰(zhàn)用 requests BeautifulSoup 編寫 Quote Scraper 名言爬蟲并導出 CSV示例工程python-mini-projects 實戰(zhàn)基于 BeautifulSoup 的 moneycontrol 金融新聞多頁爬蟲python mini projects 實戰(zhàn)基于 BeautifulSoup 的 moneycontrol 金融新聞多頁爬蟲 本文以 python mini示例工程創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考