ANALYSIS
学习路径
| 天数 | 学习目标 | 产出 | 耗时 |
|---|---|---|---|
| 第 1 天 | 用 5 行代码抓取网页标题 | 0 能运行、看到结果 | 20 分钟 |
| 第 2 天 | 学会用浏览器“检查”HTML 结构 | 能找到文章标题的标签 | 15 分钟 |
| 第 3 天 | 用 BeautifulSoup 提取多篇文章标题 | 打印出 5 篇文章标题 | 30 分钟 |
| 第 4 天 | 提取发布时间 + 链接 | 标题 + 时间 + 链接三件套 | 30 分钟 |
| 第 5 天 | 把结果保存到 articles.txt 文件 | 生成本地文件 | 20 分钟 |
| 第 6 天 | 处理常见问题(请求失败、找不到标签) | 代码更健壮 | 25 分钟 |
| 第 7 天 | 自己爬一个新网站(比如豆瓣电影 Top250) | 独立完成小项目 | 40 分钟 |
第一天
用 5 行代码抓取网页标题
PRTCL // PYTHON
import requests#导入 requests 库,用于发送 web 请求from bs4 import BeautifulSoup#导入 Beautifulsoup,用于分析网页成分
#定义 url 链接url = 'https://blog.echospace.top'#使用 requestsh 中的.get 工具访问链接response = requests.get(url)#response 拉下来的是整个 HTML 网页,还需要用美丽汤进行分析#美丽汤(获取的 HTML 使用 txt 格式,使用 html.parser 解析器进行解析soup = BeautifulSoup(response.text, 'html.parser')
#在 soup 获取的结构中找到 <title> 标签,这是快捷描述,原意为 soup.find('title')#.get_text() 是只提取目标标签中的纯文本,忽视标记等符号title = soup.title.get_text()
#答应print(title)第三天
学会用浏览器“检查”HTML 结构
PRTCL // PYTHON
# =============================================# 第 3 天:提取多篇文章标题# 功能:抓取 https://blog.echospace.top 首页所有文章的标题# 前置知识:你已通过“检查”知道标题在 <h2> 标签里,且每篇文章是 <div class="post"># =============================================
# 第 1 行:导入 requests,用于发送网络请求(就像浏览器打开网页)# 不要修改这一行,所有爬虫都需要它import requests
# 第 2 行:导入 BeautifulSoup,用于解析网页结构(帮你从 HTML 中找内容)# 不要修改这一行from bs4 import BeautifulSoup
# 第 3 行:设定目标网址(你的博客首页)# 修改建议:如果你想爬别人的网站,改这里就行(但请遵守网站规则!)url = "https://blog.echospace.top"
# 第 4 行:向目标网址发送 GET 请求,获取网页内容# requests.get(url) 会返回一个“响应对象”,我们存到变量 response 里# 注意:这一步可能会因网络问题失败,但你的博客一般不会response = requests.get(url)
# 第 5 行:检查请求是否成功(状态码 200 表示成功)# 为什么需要?避免网页打不开时程序出错# response.status_code 是一个数字,200 = 成功,404 = 页面不存在,500 = 服务器错误if response.status_code != 200: # 如果失败,打印错误信息并退出程序 print(f"❌ 请求失败!状态码: {response.status_code}") print("可能原因:网络问题、网址写错、或网站拒绝访问") exit() # exit() 是 Python 的“立即停止程序”命令else: print("✅ 网页请求成功!")
# 第 6 行:用 BeautifulSoup 解析网页内容# response.text 是网页的原始 HTML 字符串# 'html.parser' 是 Python 自带的 HTML 解析器(不用额外安装)# 结果存到变量 soup 里,后面用它来找标题soup = BeautifulSoup(response.text, 'html.parser')
# 第 7 行:【关键步骤】找到所有文章的容器# 根据你第 2 天的“检查”结果:# - 所有文章都在 <div id="posts"> 里面# - 每篇文章是一个 <div class="post"># 所以我们先找到 id="posts" 的大容器posts_container = soup.find(id='posts')
# 第 8 行:如果没找到 id="posts",说明结构变了或请求有问题if posts_container is None: print("❌ 未找到 id='posts' 的容器!") print("请打开浏览器,右键 -> 检查,确认网页结构是否还是 <div id=\"posts\">") exit()
# 第 9 行:【核心】在 posts_container 里找到所有 class="post" 的 div# .find_all() 是 BeautifulSoup 的方法,作用是“找所有匹配的标签”# 参数说明:# 'div' → 只找 <div> 标签# class_='post' → 要求 class 属性等于 "post"# 返回一个“列表”,里面是所有匹配的元素post_divs = posts_container.find_all('div', class_='post')
# 第 10 行:检查是否找到了文章# len(post_divs) 是列表的长度(即文章数量)if len(post_divs) == 0: print("❌ 未找到任何 class=\"post\" 的文章!") print("请检查网页结构是否变化") exit()
# 第 11 行:打印找到的文章数量print(f"🔍 共找到 {len(post_divs)} 篇文章")
# 第 12 行:【遍历】每一篇文章,提取标题# for 循环:对列表 post_divs 中的每一个元素(我们叫它 post),执行下面的操作# enumerate() 的作用:给每篇文章加一个序号(从 1 开始),方便打印for index, post in enumerate(post_divs, start=1):
# ========== 提取标题 ========== # 第 10 行:找 <a> 标签(因为 h2 在 a 里面) a_tag = post.find('a') if a_tag is None: title = "❗ 未找到链接标签" full_link = "无链接" else: # 第 11 行:从 a 标签里找 h2 h2_tag = a_tag.find('h2') if h2_tag is not None: # 第 12 行:提取标题文字,并去掉前后空格 / 换行 title = h2_tag.get_text(strip=True) else: title = "❗ 未找到标题"
# 第 13 行:获取链接(href 属性) href = a_tag.get('href') # .get('href') 获取 <a href="..."> 里的 ... # 第 14 行:如果链接是相对路径(以 / 开头),拼接成完整 URL if href and href.startswith('/'): full_link = "https://blog.echospace.top" + href elif href: full_link = href # 已经是完整链接(少见) else: full_link = "无链接"
# ========== 提取发布时间 ========== # 第 15 行:找包含日期的 div(class="category-and-date") date_div = post.find('div', class_='category-and-date') if date_div is None: publish_date = "❗ 未找到日期区域" else: # 第 16 行:在日期区域里找 class="date" 的 span date_span = date_div.find('span', class_='date') category_span = date_div.find('span',class_='category') if date_span is None: publish_date = "❗ 未找到日期标签" else: # 第 17 行:提取 span 里的所有文本(可能包含图标 + 日期) raw_text = date_span.get_text(strip=True)
# 第 18 行:按空白字符(空格、换行等)分割成列表 # 例如 "📅 2025/12/18" → ['📅', '2025/12/18'] parts = raw_text.split()
# 第 19 行:取最后一个元素(通常是日期) # 如果分割后有内容,取最后一项;否则写“未知” if parts: publish_date = parts[-1] # [-1] 表示“最后一个” else: publish_date = "未知日期" if category_span is None: publish_category = "! 未找到分类" else: raw_text = category_span.get_text(strip=True) parts = raw_text.split() if parts: publish_category = parts[-1] else: publish_category = "未知类目"
# ========== 打印结果 ========== # 第 20 行:输出三件套 print(f"{index}. {title}") print(f" 📅 时间: {publish_date}") print(f" 🔗 链接: {full_link}") print(f" 类别: {publish_category}\n")
# 第 18 行:为了不输出太多,只打印前 5 篇(避免刷屏) if index >= 5: print("...(只显示前 5 篇)") break # break 是“跳出循环”的命令第五天
把结果保存到 articles.txt 文件
PRTCL // PYTHON
# =============================================
# 第 5 天:保存爬取结果到 articles.txt 文件
# 功能:抓取博客文章的标题、分类、时间、链接,并写入本地文本文件
# 优势:数据不再只在屏幕上一闪而过,而是永久保存,可分享、可备份
# 注意:本代码基于你博客的真实 HTML 结构(id="posts", class="post" 等)
# =============================================
# 第 1 步:导入必需工具
import requests
from bs4 import BeautifulSoup
# 第 2 步:设定目标网址
url = "https://blog.echospace.top"
# 第 3 步:发送网络请求
response = requests.get(url)
# 第 4 步:检查请求是否成功
if response.status_code != 200:
print(f"❌ 请求失败!状态码: {response.status_code}")
exit()
else:
print("✅ 网页加载成功!")
# 第 5 步:解析网页
soup = BeautifulSoup(response.text, 'html.parser')
# 第 6 步:定位文章容器
posts_container = soup.find(id='posts')
if posts_container is None:
print("❌ 未找到 id='posts' 的容器,请检查网页结构。")
exit()
# 第 7 步:获取所有文章卡片
post_divs = posts_container.find_all('div', class_='post')
if len(post_divs) == 0:
print("❌ 未找到任何文章。")
exit()
# 第 8 步:【核心操作】打开文件,准备写入
# 'w' 模式:每次运行都会覆盖旧文件(适合更新最新文章)
# encoding='utf-8':确保中文、表情符号能正确保存(非常重要!)
# with open(...) as f:安全写法,文件用完自动关闭,避免损坏
with open('BlogDate.txt', 'w', encoding='utf-8') as f:
# 第 9 步:写入文件标题和分隔线(让文件更美观)
f.write("我的博客文章列表\n")
f.write("=" * 50 + "\n\n") # 写入 50 个等号 + 换行
# 第 10 步:只处理前 10 篇文章(避免文件过大)
for index, post in enumerate(post_divs[:10], start=1):
# --- 提取标题和链接 ---
a_tag = post.find('a')
if a_tag:
h2_tag = a_tag.find('h2')
title = h2_tag.get_text(strip=True) if h2_tag else "无标题"
href = a_tag.get('href')
# 拼接完整链接
#href.startswith,用于检查是否是 / 开头
#href.endswith,用于匹配结尾
if href and href.startswith('/'):
full_link = "https://blog.echospace.top" + href
else:
full_link = href or "无链接"
else:
title = "无标题"
full_link = "无链接"
# --- 提取分类和时间 ---
date_div = post.find('div', class_='category-and-date')
if date_div:
# 提取分类
category_span = date_div.find('span', class_='category')
publish_category = category_span.get_text(strip=True) if category_span else "未找到分类"
# 提取时间
date_span = date_div.find('span', class_='date')
if date_span:
raw_date = date_span.get_text(strip=True)
# 分割并取最后一部分(处理可能的图标)
date_parts = raw_date.split()
publish_date = date_parts[-1] if date_parts else "未知日期"
else:
publish_date = "未找到日期"
else:
publish_category = "未找到分类"
publish_date = "未找到日期"
# 第 11 步:【写入文件】将四件套按格式写入
f.write(f"{index}. {title}\n")
f.write(f" 🗂️ 分类: {publish_category}\n")
f.write(f" 📅 时间: {publish_date}\n")
f.write(f" 🔗 链接: {full_link}\n")
f.write("\n") # 空一行,分隔不同文章
# 第 12 步:写入文件尾注(可选)
f.write("-" * 50 + "\n")
f.write("数据由 Python 爬虫自动生成 | 保存时间:运行时刻\n")
# 第 13 步:提示用户文件已生成
print("✅ 成功!结果已保存到当前目录的 articles.txt 文件中。")
print("👉 请用记事本、VS Code 或其他文本编辑器打开查看。")关于我
免费提供各种技术咨询,欢迎留言私信。
原创:汪多多是只猫 专注分享实用开源工具和各种电脑技巧,让你的数字生活更自由! 关注我,发现更多好玩的工具和实用的技巧!
1 直在和电脑打交道,从给大学生清灰到折腾黑苹果,修的是机器,交的是朋友。
0 距离帮你解决问题——不管是 WiFi 连不上、系统卡顿,还是想装双系统,尽管问。
7 年折腾没停过:Ubuntu 脚本、KVM 虚拟机、数据库…我的电脑永远在“测试中”。
8 成新技能靠实战:家里整了服务器,电费每个月飞起,个人虚拟机就有 40 个。
0 基础?我也从 Shell 脚本一行行学起。普通人技术进阶总会走这些路。
1 心想做点有用的事:写明白每一篇教程,讲清楚每一个报错,不让小白踩我踩过的坑。
5 点起床调虚拟机是常态,但看到你留言“搞定啦!”,就觉得值了。
3 更半夜还在跑日志脚本?别笑,这就是我——一个爱自动化的 Linux 宅。
1 直相信:技术不该高冷,它该帮你省时间、少焦虑、多自由。
4 处漂流也想稳稳搞技术,未来希望能远程工作,边为房车旅行努力,边维护我的 40 台虚拟机 😄
R P
Rhine Lab Pioneer Division
Auth_Verified: 2026.03.21
Auth_Verified: 2026.03.21
