(声明!本教程旨在进行技术了解与学习,不可用于恶意获取隐私信息、破坏互联网绿色环境的违法行为!!!违者后果自负)
“在互联网的世界里,数据就像散落在沙滩上的珍珠。”我们通过浏览器访问网页,就像是用眼睛在看;而爬虫(Web Scraper),本质上是一段模拟人类行为的代码,它自动化地敲开目标网站的大门,将那些珍珠收集并整理到我们的口袋里。简单来说,爬虫就是‘自动化数据采集脚本’。
而最常见的爬虫编写语言就是Python,究其原因,并不是因为其他语言做不到,而是因为 Python 把这件事做到了极致的‘优雅’与‘简单’。Python 拥有一个极其庞大的生态圈,就像是一个随取随用的百宝箱:
Requests库让网络请求变得像写英语句子一样自然;
BeautifulSoup 和 lxml赋予了我们像外科医生手术刀一样精准提取数据的能力;
更不用说处理海量数据的 Pandas。
在 Python 的世界里,你不需要去关心底层的网络套接字或繁琐的内存管理,你只需要关注你的目标:数据在哪里,以及如何拿到它。
在正式开启爬虫之旅前,我们需要搭建一个稳定、高效的开发环境。
Python 解释器: 建议安装 Python 3.8 或更高版本。
编辑器(IDE): 推荐使用 VS Code 或 PyCharm。
核心库安装:
pip install requests lxml beautifulsoup4在编写爬虫之前,我们必须学会如何利用浏览器的开发者工具(F12)来透视网页的本质。
右键点击网页上你想要抓取的文字,选择“检查(Inspect)”。在弹出的 Elements 面板中,你会看到这行文字被包裹在层层叠叠的 HTML 标签里。
标签名(Tag): 如 <h1>, <p>, <a>。
类名与 ID(Class/ID):这是我们定位数据的关键索引,就像是门牌号。
点击开发者工具顶部的 Network 选项卡,然后刷新页面。你会看到密密麻麻的请求列表。
找到入口:找到那个与网页 URL 同名的请求,查看它的 Response。如果里面包含了网页的文字内容,说明这是一款“静态网页”,我们的第一关就选它。
我们通过一个最简单的页面抓取来了解爬虫的工作原理:
import requests
from bs4 import BeautifulSoup
# 1. 目标地址(以博客链接为例)
url = 'https://blog.agenblog.cn/archives/hello-halo'
# 2. 伪装请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
# 3. 发送请求
response = requests.get(url, headers=headers)
if response.status_code == 200:
# 4. 解析网页
soup = BeautifulSoup(response.text, 'html.parser')
# 5. 提取标题(保持原样)
title = soup.title.string
print(f"【文章标题】: {title}\n")
# 6. 提取正文内容
# 注意:这里的 'article' 或 'div' 需要根据实际网页结构调整
# 大多数博客的正文在 <article> 标签或类名为 content 的 div 中
# 我们这里的博客采用的halo,正文内容实际上被包裹在一个 <section> 标签里,并且带有一个特定的 CSS 类名 prose,具体可通过查看页面源代码获知
content_area = soup.find('section', class_='prose')
if content:
# get_text() 会过滤掉所有 HTML 标签,只留下纯文字
# strip=True 自动去除首尾多余的空格和换行
print("【文章正文】:")
print(content.get_text(strip=True))
else:
print("未能找到正文标签,请检查网页结构。")
else:
print(f"请求失败,状态码:{response.status_code}")
在默认情况下,Python 的 requests 库会诚实地告诉服务器:“嘿,我是一段脚本”。很多服务器出于安全考虑会直接拒绝这种请求。通过在代码中加入 User-Agent,我们将自己伪装成了一个普通的 Chrome 浏览器用户,从而大幅提高爬取的成功率。
有时候,当你满怀信心跑通代码,却发现抓回来的中文变成了‘火星文’(如 æ¤æ),别慌,你遇到了爬虫路上的第一只拦路虎:字符编码不匹配。为什么会这样?因为计算机并不认识中文,它只认识 0 和 1。中文在存储时需要经过一套规则(如 UTF-8)编码,而读取时必须用同样的规则解码。如果服务器发给你的是‘苹果’(UTF-8),你的代码却用‘香蕉’(ISO-8859-1)的规则去读,结果就是满屏乱码。因此在 Python 中,我们只需要在获取响应后增加一行简单的逻辑: response.encoding = response.apparent_encoding 。这行代码就像给爬虫配了一副‘自动对焦眼镜’,它会扫描网页内容,识别出正确的字符集,让中文瞬间‘原形毕露’。
我们还可以在原有的排版上进行优化,让它的输出格式尽可能和原有的一样,同时还可以保存在本地以方便查阅,为此我们
import requests
from bs4 import BeautifulSoup
url = 'https://blog.agenblog.cn/archives/hello-halo'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
try:
response = requests.get(url, headers=headers, timeout=10)
response.encoding = response.apparent_encoding
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser')
title = soup.title.string if soup.title else "未命名文章"
print(f"【文章标题】: {title}\n")
content_area = soup.find('section', class_='prose')
if content_area:
# 使用 separator="\n" 在标签转换时插入换行,保持易读性
final_text = content_area.get_text(separator="\n", strip=True)
print("【文章正文】:")
print(final_text)
print("\n" + "="*30)
# 8. 持久化存储:保存到本地文件
# 过滤掉标题中可能存在的非法文件名字符
safe_title = "".join([c for c in title if c not in r'\/:*?"<>|']).strip()
with open(f"{safe_title}.txt", "w", encoding="utf-8") as f:
f.write(f"标题: {title}\n")
f.write(f"来源: {url}\n")
f.write("-" * 20 + "\n")
f.write(final_text)
print(f"文件已保存为: {safe_title}.txt")
else:
print("未能找到正文标签(section.prose),请检查网页结构。")
else:
print(f"请求失败,状态码:{response.status_code}")
except Exception as e:
print(f"发生错误: {e}")
很多人在抓取正文时会发现,原本错落有致的文章,抓下来后却变成了密不透风的‘文字墙’。这是因为 HTML 中的换行是由 <p>、<br> 等标签实现的,纯粹的 get_text() 会无情地抹杀这些结构。
为了还原阅读体验,我们有两个绝招:
间隔符(Separator):在调用 get_text() 时,传入 separator="\n"。这相当于告诉爬虫:‘每当你跳过一个 HTML 标签时,请帮我按一下回车键。’
标签过滤法:通过 find_all 精准提取 <h2>(标题)、<p>(段落)和 <blockquote>(引用)。将它们存入列表后,再用 "\n\n".join() 重新缝合。
这样抓下来的数据,不仅是冷冰冰的信息,更是一篇赏心悦目的文章。