『python爬虫』20. 用协程爬取一本小说(保姆级图文)


欢迎关注 『python爬虫』 专栏,持续更新中
欢迎关注 『python爬虫』 专栏,持续更新中

1. 分析目标网站

百度小说西游记
http://dushu.baidu.com/pc/detail?gid=4306063500

在这里插入图片描述

1.1 寻找所有章节信息

  • 查看页面源码 明显源码里什么内容没有,肯定是通过ajax请求得到的数据,需要网络抓包了
    在这里插入图片描述

  • 注意此时我们这里找到的只是呈现在网页的前面几章,我们要的是全部章节
    在这里插入图片描述

  • 点击查看全部章节的按钮,此时我们抓包得到了一个新的请求
    在这里插入图片描述

  • 这样我们就得到了所有章节
    在这里插入图片描述

  • 得到了请求url http://dushu.baidu.com/api/pc/getCatalog?data={%22book_id%22:%224306063500%22}
    在这里插入图片描述

  • 访问上面的请求章节地址,得到了所有的章节
    在这里插入图片描述

  • 找到了传入的参数 data: {"book_id":"4306063500"}
    在这里插入图片描述

  • 请求中的url:http://dushu.baidu.com/api/pc/getCatalog?data={%22book_id%22:%224306063500%22}

  • 转化后的url:http://dushu.baidu.com/api/pc/getCatalog?data={book_id:4306063500}

  • 注意 %22是编码所用,把所有的%22删掉,这样我们的请求章节的url就很清晰了

1.2 寻找章节内容

  • 访问第一章节找到了第一章的内容
    在这里插入图片描述
  • 得到了请求url http://dushu.baidu.com/api/pc/getChapterContent?data={%22book_id%22:%224306063500%22,%22cid%22:%224306063500|1569782244%22,%22need_bookinfo%22:1}
    在这里插入图片描述
  • 得到了请求参数 data: {"book_id":"4306063500","cid":"4306063500|1569782244","need_bookinfo":1}
    在这里插入图片描述

2. 爬虫思路

获取得到的信息

请求章节url http://dushu.baidu.com/api/pc/getCatalog?data={data}
请求章节参数 book_id:4306063500 (书籍编号)

请求章节内容url http://dushu.baidu.com/api/pc/getChapterContent?data={data}
请求章节内容参数 data: {"book_id":"4306063500","cid":"4306063500|1569782244","need_bookinfo":1}
data格式化为下面的形式,其实不同章节的区别在于cid

    data = {
        "book_id":b_id,
        "cid":f"{b_id}|{cid}",
        "need_bookinfo":1
    }

首先要同步协程获取所有章节标题和cid写入异步任务

获取章节标题和cid的操作

async def getCatalog(url):
    resp = requests.get(url)
    dic = resp.json()
    tasks = []
    for item in dic['data']['novel']['items']:  # item就是对应每一个章节的名称和cid
        title = item['title']
        cid = item['cid']
        # 准备好后面要用到的异步任务,但是这之前的部分都是同步的操作
        tasks.append(aiodownload(cid, b_id, title))

然后根据章节标题和cid获取章节内容

#2. 异步操作: 访问getChapterContent 下载所有的文章内容
async def aiodownload(cid, b_id, title):
    data = {
        "book_id":b_id,
        "cid":f"{b_id}|{cid}",
        "need_bookinfo":1
    }
    data = json.dumps(data)

    # http://dushu.baidu.com/api/pc/getChapterContent?data={%22book_id%22:%224306063500%22,%22cid%22:%224306063500|1569782244%2
    # http://dushu.baidu.com/api/pc/getChapterContent?data={book_id:4306063500,cid:4306063500|1569782244
    url = f"http://dushu.baidu.com/api/pc/getChapterContent?data={data}"

    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            dic = await resp.json()

            async with aiofiles.open("novel/"+title, mode="w", encoding="utf-8") as f:#这里我在py文件夹同目录下新建了一个novel文件夹存放小说
                await f.write(dic['data']['novel']['content'])  # 把小说内容写入文件
                print(title+"爬取完成")



3. 完整实现代码

在这里插入图片描述
在这里插入图片描述

# http://dushu.baidu.com/api/pc/getCatalog?data={"book_id":"4306063500"}  => 所有章节的内容(名称, cid)
# 章节内部的内容
# http://dushu.baidu.com/api/pc/getChapterContent?data={"book_id":"4306063500","cid":"4306063500|11348571","need_bookinfo":1}

import requests
import asyncio
import aiohttp
import aiofiles
import json

"""
1. 同步操作: 访问getCatalog 拿到所有章节的cid和名称
2. 异步操作: 访问getChapterContent 下载所有的文章内容
"""
#1. 同步操作: 访问getCatalog 拿到所有章节的cid和名称
async def getCatalog(url):
    resp = requests.get(url)
    dic = resp.json()
    tasks = []
    for item in dic['data']['novel']['items']:  # item就是对应每一个章节的名称和cid
        title = item['title']
        cid = item['cid']
        # 准备好后面要用到的异步任务,但是这之前的部分都是同步的操作
        tasks.append(aiodownload(cid, b_id, title))
    await asyncio.wait(tasks)

#2. 异步操作: 访问getChapterContent 下载所有的文章内容
async def aiodownload(cid, b_id, title):
    data = {
        "book_id":b_id,
        "cid":f"{b_id}|{cid}",
        "need_bookinfo":1
    }
    data = json.dumps(data)

    # http://dushu.baidu.com/api/pc/getChapterContent?data={%22book_id%22:%224306063500%22,%22cid%22:%224306063500|1569782244%2
    # http://dushu.baidu.com/api/pc/getChapterContent?data={book_id:4306063500,cid:4306063500|1569782244
    url = f"http://dushu.baidu.com/api/pc/getChapterContent?data={data}"

    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            dic = await resp.json()#得到json格式数据

            async with aiofiles.open("novel/"+title, mode="w", encoding="utf-8") as f:#这里我在py文件夹同目录下新建了一个novel文件夹存放小说
                await f.write(dic['data']['novel']['content'])  # 把小说内容写入文件
                print(title+"爬取完成")



if __name__ == '__main__':
    b_id = "4306063500"#图书id
    # - 请求中的url:http://dushu.baidu.com/api/pc/getCatalog?data={%22book_id%22:%224306063500%22}
    # - 转化后的url:http://dushu.baidu.com/api/pc/getCatalog?data={book_id:4306063500}
    # - 注意 %22是编码所用,把所有的%22删掉,这样我们的请求章节的url就很清晰了
    url = 'http://dushu.baidu.com/api/pc/getCatalog?data={"book_id":"' + b_id + '"}'
    asyncio.run(getCatalog(url))

总结

大家喜欢的话,给个👍,点个关注!给大家分享更多计算机专业学生的求学之路!

版权声明:

发现你走远了@mzh原创作品,转载必须标注原文链接

Copyright 2023 mzh

Crated:2023-3-1

欢迎关注 『python爬虫』 专栏,持续更新中
欢迎关注 『python爬虫』 专栏,持续更新中
『未完待续』


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发现你走远了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值