提示:本篇代码分为基础代码和优化代码
文章目录
前言
为什么《黑神话:悟空》这么火?首先是品质过硬,据了解,这款游戏研发周期在6年左右,每小时游戏时长开发成本超过2000万元;其次是依托《西游记》这一强大文化IP,国风元素满满;更深层的原因,则是满足了无数玩家对国人开发3A级别游戏的渴望,填补了长久以来国产3A级别单机游戏的空白。
本篇文章将通过异步操作深入获取《西游记》的全部内容,在练习代码的同时,我们可以借助阅读重温这部名著的文化精髓。
提示:以下是本篇文章正文内容,下面内容可供参考
一、异步操作及相关库安装
在传统的同步编程中,每个任务都是按照顺序依次执行的。如果一个任务需要等待一些耗时的操作(如网络请求或文件读取),那么整个程序将会被阻塞,导致其他任务无法执行。而异步编程则可以在等待某些任务的同时,继续执行其他任务,从而充分利用系统资源,提高程序的性能。asyncio是Python用于解决异步IO编程的标准库之一,它利用事件循环和协程使得异步编程更加直观和易于理解。
1.1基本概念
异步函数 (async def):
使用 async def 定义异步函数。
异步函数返回一个协程对象,通常需要用 await 关键字来调用异步函数。
协程 (asyncio 库):
协程是可挂起的函数,可以在它执行的过程中让出控制权给其他协程。
asyncio 是 Python 的标准库,用于编写异步代码。
await 关键字:
用于暂停协程的执行,直到某个异步操作完成。
只能在异步函数中使用。
事件循环 (asyncio 的事件循环):
负责调度和管理协程的执行。
1.2 aiohttp,aiofiles介绍及配置
1.2.1 aiohttp库
aiohttp 是一个用于在 Python 中进行异步 HTTP 请求的库。它支持异步 HTTP 客户端和服务器功能,基于 asyncio 实现。通过 aiohttp,你可以在异步编程环境中高效地处理 HTTP 请求和响应。
1.2.2 aiofiles库
aiofiles是一个Python库,它提供了异步文件操作的功能,基于Python的asyncio库。 通过使用aiofiles,我们可以在异步程序中进行文件的读取、写入和操作,而不会阻塞事件循环。 这对于需要处理大量文件或需要与其他异步操作结合的场景非常有用。
1.2.3安装第三方库
在pycharm终端使用pip命令即可安装:
pip install aiohttp
pip install aiofiles
二、思路及代码
1.思路
1.1 分析网页
如下:
1.先找到百度小说《西游记》初始页面的内容:
进入百度小说中《西游记》对应网页,进入开发者模式,左侧小说页面点击查看全部,右侧抓包工具将接到响应。
接着,我们点击响应,这里我们可以看到本书的所有章节。title,cid这些数据我们需要获取。
2.进入第一回章节内容页面:我们需要这个url。
继续点击响应可以找到“content”,这里是本回的文本内容。
1.1.2 代码逻辑
1.对初始页面进行requests相关操作,获取“title”,“cid”这些数据
2.对小说每一回页面进行异步asyncio对应操作,获取“content”信息。
3.处理url格式,编写对应方法并调用
2.基础代码
代码如下(示例):
import asyncio
import aiofiles
import aiohttp
import requests
import json
async def getCatalog(url):
resp = requests.get(url)
dic = resp.json()
tasks = []
for item in dic['data']['novel']['items']:
title = item['title']
cid = item['cid']
tasks.append(aiodownload(b_id, cid, title))
# Python3.8版本后摒弃了await asyncio.wait(tasks)
await asyncio.gather(*tasks)
async def aiodownload(b_id, cid, title):
# https://dushu.baidu.com/api/pc/getChapterContent?data={%22book_id%22:%224306063500%22,%22cid%22:%224306063500|1569782244%22,%22need_bookinfo%22:1}
# %22 %22 替换为 “”,data 用字典表示更方便
data = {"book_id": b_id,
"cid": f"{b_id}|{cid}",
"need_bookinfo": 1}
data = json.dumps(data)
url = f"https://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(title, "w",encoding="utf-8") as f:
await f.write(dic["data"]["novel"]["content"])
if __name__ == '__main__':
b_id = "4306063500"
url = 'https://dushu.baidu.com/api/pc/getCatalog?data={"book_id":' + b_id + '}'
asyncio.run(getCatalog(url))
2.1运行结果展示
三、探讨——代码优化
该代码有很多优化空间,我们主要针对以下两各方面进行代码优化:
1.顺序性
因为是异步爬取,所以得到的章回列表是乱序的,但我们可以在aiodownload方法内按照cid大小进行动态排列。
2.规范性
为了规范操作,我们将爬取的信息以txt文件存入文件夹(注意将文件设置为excluded),另外我们规定txt文件每行信息的长度,以便于提升阅读体验。这些优化均在aiodownload方法中进行(详情见优化代码)
规范后的小说文件列表以及txt文件展示:
3.优化代码
这里我们引入了os库方便设置文件存放路径,优化在aiodownload方法中,包括:
1:设置文件path,以cid大小顺序排列章回列表
2:设定每行最大长度,便于读者阅读txt内容
import asyncio
import aiohttp
import requests
import json
import aiofiles
import os
async def aiodownload(cid, b_id, title):
data = {
"book_id": b_id,
"cid": f"{b_id}|{cid}",
"need_bookinfo": 1
}
data = json.dumps(data)
url = f'https://dushu.baidu.com/api/pc/getChapterContent?data={data}'
# 优化:设置文件path,以cid大小顺序排列章回列表
file_path = os.path.join("novel", f"{cid}-{title}.txt")
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
dic = await resp.json()
content = dic["data"]["novel"]["content"]
# 优化:设定每行最大长度,便于读者阅读txt内容
# 设置每行的最大长度
max_line_length = 80
# 分割长字符串为固定长度的行
lines = [content[i:i + max_line_length] for i in range(0, len(content), max_line_length)]
# 将分割后的行写入文件
async with aiofiles.open(file_path, mode='w', encoding="utf-8") as f:
for line in lines:
await f.write(line + '\n')
async def getCatalog(url):
resp = requests.get(url)
dic = resp.json()
tasks = []
for item in dic["data"]["novel"]["items"]:
title = item["title"]
cid = item["cid"]
# 不用async修饰也可以用 asyncio.run(asyncio.wait(tasks))
tasks.append(aiodownload(cid, b_id, title))
await asyncio.gather(*tasks)
if __name__ == '__main__':
b_id = "4306063500"
url = 'https://dushu.baidu.com/api/pc/getCatalog?data={"book_id":"' + b_id + '"}'
asyncio.run(getCatalog(url))
总结
本篇内容介绍了异步爬取的相关知识,并深入讲解了异步爬取《西游记》完整内容的思路、操作步骤、及代码优化。代码仍有优化空间,读者可以借助本篇内容巩固爬虫异步操作的知识。
参考链接:Python标准库asyncio官方文档