新手学习爬虫的案例
首先你的电脑上肯定已经安装了python,没安装的去官网安装,我使用的是Pycharm作为操作的IDE
环境准备
安装必要的库
爬虫需要用到requests和beautifulsoup4
使用命令行或者终端运行下面的命令
pip install requests beautifulsoup4 -i https://mirrors.aliyun.com/pypi/simple
这里使用的是阿里云的镜像源,下载的快一点
下载完成之后可以使用下面这段代码检验下载的结果
import requests
from bs4 import BeautifulSoup
print("所有库安装成功!")
封面等内容的爬取
接下来是一段爬虫的代码,我们逐行对它进行讲解
import requests
from bs4 import BeautifulSoup
# 1. 定义目标URL
url = "http://books.toscrape.com/"
try:
# 2. 发送HTTP请求
response = requests.get(url)
# 检查请求是否成功(状态码200表示成功)
response.raise_for_status()
# 3. 解析HTML内容
soup = BeautifulSoup(response.text, "html.parser")
# 4. 定位所有书籍的容器
books = soup.find_all("article", class_="product_pod")
# 5. 遍历每个书籍容器并提取信息
for book in books:
# 提取书名
title = book.h3.a["title"]
# 提取价格
price = book.find("p", class_="price_color").text
# 提取评分(例如:"Three" -> 3星)
rating = book.p["class"][1]
# 打印结果
print(f"书名: {title}")
print(f"价格: {price}")
print(f"评分: {rating} 星")
print("-" * 50)
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
except Exception as e:
print(f"发生错误: {e}")
分步详解
-
导入库
import requests # 用于发送HTTP请求 from bs4 import BeautifulSoup # 用于解析HTML
-
发送HTTP请求
url = "http://books.toscrape.com/" response = requests.get(url) response.raise_for_status() # 如果状态码不是200,抛出异常
requests.get(url):向目标URL发送GET请求。
response.raise_for_status():检查请求是否成功(状态码200),失败则抛出异常。 -
解析HTML内容
soup = BeautifulSoup(response.text, "html.parser")
response.text:获取网页的HTML文本内容
BeautifulSoup():将HTML文本转换为可操作的对象(DOM树)。 -
定位书籍容器
books = soup.find_all("article", class_="product_pod")
find_all():查找所有符合条件的目标元素。
article 是标签名,class="product_pod" 是类名(注意 class_ 的写法)。 -
提取书籍信息
for book in books: title = book.h3.a["title"] # 书名存储在a标签的title属性中 price = book.find("p", class_="price_color").text # 价格在p标签的文本中 rating = book.p["class"][1] # 评分在p标签的第二个类名中(如 "star-rating Three")
book.h3.a["title"]:通过层级关系直接定位到书名。
find("p", class="price_color"):在书籍容器内查找价格元素。
book.p"class":评分通过类名的第二部分获取(例如 Three 表示3星)。 -
错误处理
except requests.exceptions.RequestException as e: print(f"请求失败: {e}") except Exception as e: print(f"发生错误: {e}")
捕获网络请求错误和其他异常,避免程序崩溃。 运行结果示例
运行结果示例
书名: A Light in the Attic 价格: £51.77
评分: Three 星
书名: Tipping the Velvet 价格: £53.74
评分: One 星
...
与该网站中的信息进行比对,发现爬取成功
接下来我们进入每一本书的详情页面,并爬取该页面中的Product_Description
详情页面爬取
将上面的代码更改为下面这一段代码
import requests
from bs4 import BeautifulSoup
import os
# 目标网站
url = "http://books.toscrape.com/"
# 创建文件夹保存图片
if not os.path.exists("book_covers"):
os.makedirs("book_covers")
try:
# 发送请求
response = requests.get(url)
response.raise_for_status()
# 解析HTML
soup = BeautifulSoup(response.text, "html.parser")
books = soup.find_all("article", class_="product_pod")
for book in books:
# 提取书名(用于命名图片文件)
title = book.h3.a["title"].strip().replace("/", "-") # 去除非法字符
# 提取封面图片的相对路径(如:../../media/.../image.jpg)
image_relative_url = book.img["src"]
# 将相对路径转换为绝对URL
image_absolute_url = url + image_relative_url.replace("../", "")
# 下载图片
image_response = requests.get(image_absolute_url, stream=True)
image_response.raise_for_status()
# 保存图片到本地
filename = f"book_covers/{title}.jpg"
with open(filename, "wb") as f:
for chunk in image_response.iter_content(1024):
f.write(chunk)
print(f"已下载封面: {title}")
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
except Exception as e:
print(f"发生错误: {e}")
分步解释
-
创建保存图片的文件夹
import os if not os.path.exists("book_covers"): os.makedirs("book_covers")
使用 os 模块检查并创建文件夹,避免重复下载时文件覆盖。
-
定位封面图片的URL
查看图片的HTML结构: 右键点击封面图片 → 检查,发现结构如下:
<img src="../../media/cache/2c/da/2cdad67c.../a-light-in-the-attic_1000.jpg" alt="A Light in the Attic" class="thumbnail">
src 属性包含图片的 相对路径(如 ../../media/...)。
处理相对路径
相对路径需要拼接网站的完整URL:
image_relative_url = book.img["src"] # 例如:../../media/... image_absolute_url = url + image_relative_url.replace("../", "")
url 是基础地址(All products | Books to Scrape - Sandbox)。 替换 ../ 为空字符串,得到完整路径(如 http://books.toscrape.com/media/...)。
-
下载并保存图片
image_response = requests.get(image_absolute_url, stream=True) with open(filename, "wb") as f: for chunk in image_response.iter_content(1024): f.write(chunk)
stream=True:以流式下载大文件,避免内存溢出。 iter_content(1024):每次下载 1024 字节的块,适合大文件。
-
文件名处理
title = book.h3.a["title"].strip().replace("/", "-") filename = f"book_covers/{title}.jpg"
replace("/", "-"):替换书名中的非法字符(如斜杠),避免保存文件时报错。
运行结果
已下载封面: A Light in the Attic 已下载封面: Tipping the Velvet 已下载封面: Soumission ... 所有封面图片会保存在 book_covers 文件夹中,文件名格式为 书名.jpg。
扩展优化
处理分页
爬取所有页面的书籍封面(观察分页URL规律,如 page-2.html):
for page in range(1, 51): # 共50页 url = f"http://books.toscrape.com/catalogue/page-{page}.html" # 发送请求并解析...
添加延迟避免封禁
在请求间添加随机延迟,模拟人类操作:
import time import random time.sleep(random.uniform(0.5, 2.0)) # 随机延迟0.5~2秒
错误重试机制
使用 try-except 捕获下载失败的图片并重试:
try: image_response = requests.get(...) except requests.exceptions.RequestException: print(f"下载失败: {title}") continue # 跳过当前,继续下一个