协程爬取小说

前言

大家好!欢迎来到我的博客。今天,我要给你们带来一份超有趣、简单易懂的爬虫教程。我们的目标是爬取千千小说网站上的小说章节内容(而且能够实现章节的顺序排放哦)然后保存到本地文件。准备好了吗?现在就让我们开始这场精彩的编程之旅吧!
目标网址:万古神帝 https://www.qqxsnew.net/12/12776/

1. 首先,让我们来看看程序的主角——Novel类

class Novel:
    RIGHT = 0

这个类就是我们的爬虫主体,RIGHT属性用来记录成功下载的章节数量。下面,我们来为这个类添加一些方法。

2. 初始化函数__init__及其他常用函数

  def __init__(self):
           self.url = 'https://www.qqxsnew.net/12/12776/'
           self.headers = {
               'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0
       Safari/537.36'
           }

__init__方法用来初始化novel对象。其中,url是我们要爬取的小说网址,headers则是请求头信息,让我们的爬虫更像一个正常的用户。

3. 下载章节的异步方法download_chapter

这个方法会异步地下载小说的每个章节。首先,我们让爬虫稍微休息一下,以免给服务器带来太大压力。接着,获取网页内容并提取章节标题和内容。注意,我们使用了chinese2digits库来将中文数字转换成阿拉伯数字,让文件名更规范。

    async def download_chapter(self, session, url, title):
        await asyncio.sleep(random.randint(500, 800) / 1000)
        res = await session.get(url)
        data = await res.read()
        html_data = etree.HTML(data)
        # title=c2d.takeNumberFromString(html_data.xpath('//*[@id="main"]//div[2]/h1/text()')[0])['replacedText']
        try:
            if title.startswith('第'):
                ret = re.search(r'(第.*?章)(.*)', title)
                title = c2d.takeNumberFromString(ret.group(1))['replacedText']
                new_title = title + ret.group(2)
                content = html_data.xpath("string(//*[@id='content'])").strip()  # 获取所有文本
                pattern = re.compile(
                    r'下载星星阅读app,阅读最新章节内容无广告免费|想要看最新章节内容,请下载星星阅读app,无广告免费阅读最新章节内容。网站已经不更新最新章节内容,已经星星阅读小说APP更新最新章节内容。|(无尽的昏迷过后,时宇猛地从床上起身。).*|QqXsΝεW.net|ωωw.qqχsΠéω.net',
                    re.S)
                new_content = re.sub(pattern, '', content)
                await self.save(new_content, new_title)
            else:
                content = html_data.xpath("string(//*[@id='content'])").strip()
                pattern = re.compile(
                    r'下载星星阅读app,阅读最新章节内容无广告免费|想要看最新章节内容,请下载星星阅读app,无广告免费阅读最新章节内容。网站已经不更新最新章节内容,已经星星阅读小说APP更新最新章节内容。|(无尽的昏迷过后,时宇猛地从床上起身。).*|QqXsΝεW.net|ωωw.qqχsΠéω.net',
                    re.S)
                new_content = re.sub(pattern, '', content)
                await self.save(new_content, title)
        except Exception as e:
            print(e)

最后,我们调用save方法将内容保存到本地文件。

4. 保存章节内容的异步方法save

async def save(self, content, title):
    path = './小说/' #这里填写你要保存的路径哦
    if not os.path.exists(path):
        os.mkdir(path)
    async with aiofiles.open(path + f'/{title}.txt', 'a', encoding='utf-8') as f:
        self.RIGHT += 1
        await f.write(content)
        logger.success(f'download {title} right {self.RIGHT}...')

save方法将章节内容保存到本地文件。这里,我们使用了aiofiles库来异步地写入文件。logger.success会输出保存成功的信息。

5. 主函数main

async def main(self):
    async with aiohttp.ClientSession(headers=self.headers) as session:
        res = await session.get(self.url)
        data = await res.text()
        html_data = etree.HTML(data)
        dd_lst = html_data.xpath("//*[@id='list']/dl/dd[position()>15]/a")
        tasks = []
        for dd in dd_lst:
            title = dd.xpath('./text()')[0]
            chapter_url = 'https://www.qqxsnew.net/' + str(dd.xpath('./@href')[0])
            task = asyncio.create_task(self.download_chapter(session, chapter_url, title))
            tasks.append(task)
        await asyncio.gather(*tasks)

在main方法中,我们首先获取小说目录页的内容,然后提取出所有章节的链接。接着,我们创建一个任务列表,将下载章节的任务添加到列表中。最后,使用asyncio.gather同时运行所有任务。

6. 运行我们的爬虫

if __name__ == '__main__':
    t = time.time()
    novel = Novel()
    loop = asyncio.get_event_loop()
    loop.run_until_complete(novel.main())
    print("总耗时:", time.time() - t)

这是效果运行图,风一样的男子哇!
在这里插入图片描述

最后,我们创建一个Novel对象,并运行main方法,启动我们的爬虫。
到此,我们的爬虫教程就结束了。现在,你是否已经学会了呢?
友情提示:不建议用异步的方式来抓取页面,这样会给人家的服务器造程很大的伤害,如果一定要用,请加一定的延迟时间,最好两秒以上哦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值