聚焦千千小说:一篇幽默风趣的网络小说爬虫教程
大家好!欢迎来到我的博客。今天,我要给你们带来一份超有趣、简单易懂的爬虫教程。我们的目标是爬取千千小说网站上的小说章节内容(而且能够实现章节的顺序排放哦)然后保存到本地文件。准备好了吗?现在就让我们开始这场精彩的编程之旅吧!
目标网址:万古神帝 /12/12776/
1. 首先,让我们来看看程序的主角——Novel类
class Novel:RIGHT = 0
这个类就是我们的爬虫主体,RIGHT属性用来记录成功下载的章节数量。下面,我们来为这个类添加一些方法。
2. 初始化函数__init__及其他常用函数
def __init__(self):self.url = '/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.0Safari/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 = pile(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 = pile(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 += 1await 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 = '/' + 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方法,启动我们的爬虫。
到此,我们的爬虫教程就结束了。现在,你是否已经学会了呢?
友情提示:不建议用异步的方式来抓取页面,这样会给人家的服务器造程很大的伤害,如果一定要用,请加一定的延迟时间,最好两秒以上哦。