Python爬虫学习记录—— BooksToScrape分页爬取与图片下载

前面是踩坑和总结,完整代码在最后

目标网站为:

https://books.toscrape.com/

主要内容

  • 分页爬取
  • URL拼接
  • CSV数据存储
  • CSV读取
  • 图片下载
  • 常见编码错误处理

一、分页爬取的核心思想

直接写只能获取首页数据:

python 复制代码
url = "https://books.toscrape.com/"

res = requests.get(url)

但网站实际上有50页数据。

分页爬取的本质:

text 复制代码
请求当前页
    ↓
解析数据
    ↓
找到下一页链接
    ↓
拼接URL
    ↓
继续请求

因此最终采用:

python 复制代码
while url:

    # 请求页面

    # 解析数据

    # 获取下一页

    # 更新url

二、不要手动拼接URL

这是我最开始写法:

python 复制代码
next_url = url + next_href

例如:

python 复制代码
base_url = "https://books.toscrape.com/"
next_href = "page-3.html"

得到:

python 复制代码
https://books.toscrape.com/page-3.html

这是错误的。

因为当前页面实际上位于:

python 复制代码
https://books.toscrape.com/catalogue/page-2.html

正确地址应该是:

python 复制代码
https://books.toscrape.com/catalogue/page-3.html

解决方案:

python 复制代码
from urllib.parse import urljoin

next_url = urljoin(url, next_href)

以后遇到:

python 复制代码
../
./
/path

等相对路径时都能自动处理。


三、next按钮不存在时的错误

最开始写法:

python 复制代码
next_href = soup.find(
    "li",
    class_="next"
).find("a")["href"]

当最后一页没有next按钮时:

python 复制代码
soup.find("li", class_="next")

返回:

python 复制代码
None

程序报错:

python 复制代码
AttributeError:
'NoneType' object has no attribute 'find'

正确写法:

python 复制代码
next_li = soup.find(
    "li",
    class_="next"
)

if next_li is None:
    break

next_href = next_li.find("a")["href"]

四、CSV写入位置问题

错误写法:

python 复制代码
while url:
    with open(
        "books.csv",
        "w"
    ) as f:

        writer.writerow(...)

问题:

每次循环都会重新创建文件。

结果:

text 复制代码
第一页数据被覆盖
第二页数据被覆盖
第三页数据被覆盖
...

最后只剩最后一页。

正确写法:

python 复制代码
with open(
    "books.csv",
    "w",
    newline="",
    encoding="utf-8-sig"
) as f:

    writer = csv.writer(f)

    writer.writerow(
        ["书名","价格","库存","封面"]
    )

    while url:

        writer.writerow(...)

文件只打开一次。


五、CSV编码问题

保存时:

python 复制代码
with open(
    "books.csv",
    "w",
    encoding="utf-8-sig"
)

从csv文件读取内容不要忘记指定编码:

python 复制代码
with open(
    "books.csv",
    "r"
)

导致:

text 复制代码
UnicodeDecodeError

原因:

Windows默认使用GBK读取。

而文件实际编码:

text 复制代码
utf-8-sig

解决:

python 复制代码
with open(
    "books.csv",
    "r",
    encoding="utf-8-sig"
)

读写编码必须一致。


六、enumerate的使用

python 复制代码
for i, item in enumerate(
    data,
    start=1
):
    pass

优点:

  • 代码更简洁
  • 自动计数
  • 可指定起始值

例如:

python 复制代码
for i, item in enumerate(
    reader,
    start=1
):

得到:

text 复制代码
1
2
3
...

七、下载图片

读取CSV中的图片地址:

python 复制代码
reader = csv.DictReader(f)

for row in reader:

    img_url = row["封面"]

下载:

python 复制代码
res = requests.get(
    img_url,
    headers=headers,
    proxies=proxy,
    timeout=10
)

保存:

python 复制代码
with open(
    filename,
    "wb"
) as file:

    file.write(res.content)

注意:

python 复制代码
wb

表示二进制写入。

图片、视频等文件都要使用:

python 复制代码
wb

八、限制下载前10张图片

实现:

python 复制代码
for i, row in enumerate(
    reader,
    start=1
):

    if i > 10:
        break

只下载:

text 复制代码
image_1.png
image_2.png
...
image_10.png

用于测试非常方便。


九、本次项目最终结构

text 复制代码
请求首页
    ↓
解析书籍数据
    ↓
写入CSV
    ↓
寻找下一页
    ↓
翻页
    ↓
保存全部数据
    ↓
读取CSV
    ↓
下载图片

已经完成:

✅ Requests基础使用

✅ BeautifulSoup解析

✅ 分页爬取

✅ URL拼接

✅ CSV存储

✅ CSV读取

✅ 图片下载


十、完整代码

python 复制代码
import requests
from urllib.parse import urljoin
from bs4 import BeautifulSoup
import csv
import os

url = "https://books.toscrape.com/"

#代理,端口改成自己的
proxy = {
    "http":"http://127.0.0.1:7892",
    "https":"http://127.0.0.1:7892"
}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
    "Accept-Encoding": "gzip, deflate, br",
    "Connection": "keep-alive"
}

def get_books():
    global url
    num = 0

    with open("book_1.csv","w",newline="",encoding="utf-8-sig") as f:
            writer = csv.writer(f)

            writer.writerow(["书名","价格","库存","封面"])    

            while url:
                num+=1
                res = requests.get(url,proxies=proxy,headers=headers,timeout=10)
                soup = BeautifulSoup(res.text,"html.parser")

                #解析书籍
                articles = soup.find_all("article",class_="product_pod")
                for article in articles:
                    title = article.find("h3").find("a")["title"]
                    price = article.find("p",class_="price_color").text.strip()
                    instock = article.find("p",class_="instock availability").text.strip()
                    img_url = urljoin(url,article.find("img")["src"])
                
                    writer.writerow([title,price,instock,img_url])
                print(f"当前第{num}页数据写入完成")
                
                #找next,没有直接退出
                next_li = soup.find("li",class_="next")

                if next_li is None:
                    print("爬取完成")
                    break
                
                next_url = next_li.find("a")["href"]

                url = urljoin(url,next_url)


#保存图片
def save_image():
    makedir = "down"
    os.makedirs(makedir,exist_ok=True)

    with open("book_1.csv","r",encoding="utf-8-sig") as f:
        reader = csv.DictReader(f)

        for i,read in enumerate(reader,start=1):

            img_url = read["封面"]

            res = requests.get(img_url,headers=headers,proxies=proxy,timeout=10)

            if i>=10 :
                print("保存成功")
                break
            filename = os.path.join(makedir,f"image_{i}.png")

            with open(filename,"wb") as file:
                file.write(res.content)
             
            
if __name__ == "__main__":
    get_books()
    save_image()
相关推荐
FoldWinCard1 小时前
D6 Python 基础语法 --- 保留关键字
开发语言·python
暮暮祈安1 小时前
Celery 新手入门指南
java·数据库·python·flask·httpx
风吹心凉2 小时前
python3基础2026.7.22
开发语言·python
小猴子爱上树3 小时前
一站式解决图片视频翻译难题的高效AI工具
人工智能·python·音视频
weixin_538601973 小时前
智能体测开Day31
开发语言·python
lbb 小魔仙4 小时前
Git + Python 项目工作流最佳实践:pre-commit、CI、CHANGELOG 自动化
git·python·ci/cd
dyxal4 小时前
最长公共子序列(LCS)
python·算法
你驴我4 小时前
WhatsApp Cloud API 速率限制下的令牌桶与退避策略实践
网络·后端·python
AC赳赳老秦4 小时前
司法公开数据采集应用:OpenClaw 抓取裁判文书公开信息,批量整理同类参考案例
java·大数据·python·数据挖掘·数据分析·php·openclaw
小大宇5 小时前
Python 集成 Conda
开发语言·python·conda