目录
- 1. 分析目标网站
- 1.1 寻找所有章节信息
- 1.2 寻找章节内容
- 2. 爬虫思路
- 获取得到的信息
- 首先要同步协程获取所有章节标题和cid写入异步任务
- 然后根据章节标题和cid获取章节内容
- 3. 完整实现代码
- 总结
欢迎关注 『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爬虫』 专栏,持续更新中
『未完待续』