Python + aardio实现快速开发小说爬取的桌面应用


前言

最近刷到一个视频,介绍了一款没听说过的工具语言aardio,其体积小巧,永久免费,并且兼容市面上大多数语言。这么神奇的吗?我直接光速打开其官网,定睛一看,6.5MB大小!于是我毫不犹豫的点击了下载,安装启动一气呵成,可是…我要拿它做什么用呢?
诶! 最近在学习爬虫,正好找个对象练练手,于是我将目光转向了大名鼎鼎的笔趣阁,打开浏览器搜索笔趣阁,woc,这也太多了吧,我翻看了浏览器前几页,就起码找到了几十个可以正常使用的笔趣阁。
好嘛,说干就干,随便找了一个看起来还可以的网站,敲下了键盘上的 F12
… …


一、搜索功能

既然是爬小说,那一定不能只爬取单独一本小说吧,所以我们需要根据输入的书名进行定向内容爬取,于是我点击该网站的搜索框,直接输入了一本比较知名的玄幻小说名称,然后点击【搜索】,额… …
如下图所示,竟然要验证!!!
竟然要验证
经过多次尝试,这个网站的验证码是四位纯数字的形式,网上有挺多付费识别这类验证码的平台,但是我们总不能为了看盗版小说而付费吧,不值当也没必要,再说了,这本就是一次对自身技术的考验…
于是我尝试使用orc去识别该验证码,简单搜索了一下,选用了Tesseract-OCR去实现该功能,经过安装库,语言包等操作,搭建好所需要的环境后,开始尝试识别,可惜事与愿违,通用模型的准确率太低了,我又太不会自己训练模型…
好吧,只能暂时放弃自动识别这一条路,选择了手动输入这一条路。话不多说,我们直接获取验证码图片内容。

获取验证码图片

import os
import random
import time
import requests
import io
def download_image(url, save_path):
    timestamp = int(time.time()) - 10
    jieqi = str(timestamp - random.randint(20, 100))
    cookies = {
        #省略了部分固定内容
        'jieqiVisitTime': 'jieqiArticlesearchTime%3D' + jieqi,
        'Hm_lpvt_dbd0a5819ad389f6d69d1b451da153bc': str(timestamp),
        'Hm_lpvt_a71b1bc761fe3f26085e79b5fd6a7f71': str(timestamp),
    }
    headers = {
		# 省略,一般情况下有user-agent就能运行了
    }
    try:
        response = requests.get(url,cookies=cookies, headers=headers)
        if response.status_code == 200:
            with open(save_path, 'wb') as f:
                f.write(response.content)
    except Exception as e:
        print(f"错误: {e}")

def down_img():
    image_url = "https://www.biquxsw.cc/checkcode.php"
    save_directory = " " #存储路径
    filename = "yzm.png" #验证码图片名称
    if not os.path.exists(save_directory):
        os.makedirs(save_directory)
    full_save_path = os.path.join(save_directory, filename)
    download_image(image_url, full_save_path)

# 这里的mainForm是aardio里面导出的页面文件,暂时不用管
def get_img(mainForm):
    down_img()
    with open(" 文件路径 ", "rb") as f:
        img_bytes = io.BytesIO()
        img_bytes.write(f.read())
    #将图片展示在程序里
    mainForm.plus.setBackground(img_bytes.getvalue(),False)
    return 

# 我们可以测试一下,只需要调用down_img()函数即可
# if __name__ == "__main__":
#     print(down_img())

打开我们预先指定的保存路径文件夹
在这里插入图片描述
在指定路径文件夹下我们成功找到了保存下来的验证码图片,很好,第一步算是解决了。

通过书名搜索小说

既然验证码的问题已经解决后,搜索功能自然轻而易举的就能完成,在完成验证码验证后,根据书名我们会跳转进入搜索结果页面,该页面有两种情况,第一种情况占绝大多数情况,就是页面中出现多本符合搜索内容的小说,需要再一次选择,点击我们需要阅读的小说后,才会跳转至该小说主页,另一种情况则是当搜索书名只有一本小说匹配时,会直接进入到该小说主页。
我们以第一种情况举例(第二种情况直接忽略掉筛选部分即可)

import random
import re
import time
import requests
from urllib.parse import quote
from lxml import etree

def get_book(bookURL,code):
    timestamp = int(time.time()) - 10
    jieqi = str(timestamp - random.randint(20, 100))
    cookies = {... ...}
    headers = {... ...}
	# cookies 和 headers 同上 唯一需要修改的是小说对应的链接bookURL和验证码code
    data = 'searchtype=articlename&searchkey=' + bookURL + '&checkcode=' + code
    pageText = requests.post('https://www.biquxsw.cc/modules/article/search.php', 
    cookies=cookies, headers=headers, data=data)
    tree = etree.HTML(pageText.text)
    pageUrl = pageText.url
	# 正则匹配bookURL后缀是否有php,有php则是上诉提到的第一种情况,反之第二种,直接获取到小说对应的url
    pattern = r'\.php$'
    if re.search(pattern, pageUrl):
        tree = etree.HTML(pageText.text)
        content_list = tree.xpath('/html/body/div[2]/div/div[1]/li')
        num_list = []
        bookNameList = []
        bookUrlList = []
        authorList = []
        with open('D:/BiQuGe_cache/res/bookUrl.txt', 'w', encoding='utf-8') as f:
            for i in range(len(content_list)):
                bookName = content_list[i].xpath('./span[2]/a/text()')[0]
                bookUrl = content_list[i].xpath('./span[2]/a/@href')[0]
                author = content_list[i].xpath('./span[4]/text()')[0]
                num_list.append(i+1)
                bookNameList.append(bookName)
                bookUrlList.append(bookUrl)
                authorList.append(author)           
                f.write(bookUrl + '\n')
        f.close()  
        return '\n'.join(f"【{num:^3}】\t{name:<32}\t{author:>26}\r\n" for num,name, author in 
        zip(num_list,bookNameList, authorList))
    else:
        name = tree.xpath('//*[@id="info"]/h1/text()')[0]
        author = tree.xpath('//*[@id="info"]/p[1]/a/text()')[0]
        with open('D:/BiQuGe_cache/res/bookUrl.txt', 'w', encoding='utf-8') as f:
            f.write(pageUrl)
        f.close()
        return f"【{'1':^3}】\t{name:<32}\t{author:>26}\r\n"

def  toUrl(bookName):
    # 使用quote函数对字符串s进行URL编码
    encoded_s = quote(bookName.encode('gbk')).upper()
    return encoded_s

def searchBook(mainForm):
    bookName = mainForm.edit.text
    code = mainForm.edit3.text
    mainForm.edit2.text = get_book(toUrl(bookName),code)

到这里为止,我们已经成功获取小说的书名,作者和链接,只需要根据作者名称,便能得知我们需要的是哪一本小说。

二、获取小说内容

获取章节URL

def get_url(book_url):
    pageText = requests.get(book_url, headers=headers).text
    tree = etree.HTML(pageText)
    chapter_list = tree.xpath('//div[@id="list"]/dl/dd')
    if(len(chapter_list) >= 12):
        chapter_list = chapter_list[12:]
    with open('存储路径', 'w') as f:
        for chapter in chapter_list:
            try:
                chapter_url = chapter.xpath('./a/@href')[0]
                f.write(book_url + chapter_url + '\n')
            except:
                pass
        print(chapter_url)
    f.close()

通过上面这个函数,我们可以使用之前获取的小说链接去获取全部章节链接。

获取章节正文

有了章节连接后,我们就可以直接通过其进入章节正文,然后便可以直接爬取章节正文了,具体操作如下。

def get_content(chapter_url):
    pageText = requests.get(chapter_url, headers=headers).text
    tree = etree.HTML(pageText)
    content_list = tree.xpath('//*[@id="content"]/text()')
    content = ''
    title = tree.xpath('//*[@id="box_con"]/div[2]/h1/text()')[0]
    for i in range(1,len(content_list)):
        content += content_list[i].replace('\xa0', '') + '\r\n\r\n'
    # 返回章节名和正文,方便后续展示
    return title,content

本地化储存

我们已经爬取到正文了,自然需要将其本地化保存才方便后续浏览嘛,这也简单,直接储存在TXT文件中即可。

def write_book(chapter_url,path):
    try:
        print('write_book')
        result = get_content(chapter_url)
        title = result[0]
        content = result[1]
        with open(f'{path}/{title}.txt', 'w', encoding='utf-8') as f:
            f.write(content)
        f.close()
        tip = '【下载成功】'
        tag = f'{tip}\t{title}\r\n'
        return tag
    except:
        return 'write_book出现错误!'

至此,我们从笔趣阁爬取小说的全部功能已经实现,接下来便是实现桌面窗口程序。


三、桌面程序的制作

我们在一开始便提到了aardio这个神奇的语言,自然要使用它完成一个简单的可视化桌面程序,不了解的小伙伴不用着急,只要拥有一些编程基础的小伙伴,可以进入aardio官方网站浏览一下官方文档,单纯只是想制作一个可以使用的程序还是非常简单的,只需要简单浏览一下其基础语法和如何调用python代码即可。(博主我也只学习了半天的时间,就直接上手了,不会的部分可以看官方案例,大部分需要解决的功能都能找到。)

创建窗口程序

创建流程如下:
在这里插入图片描述

搭建操作界面

直接使用官方提供的组件,我们即可完成所需要的全部功能,例如通过输入框输入验证码、书名,展示返回的文本内容,图片框展示验证码,按键执行我们所设定好的操作逻辑,例如搜索,下载…
页面控件如下图:
在这里插入图片描述
简单展示一下我的页面
在这里插入图片描述

调用python代码

这里我以显示验证码和搜索为例子简单展示一下

显示验证码

py3.exec($"\res\get_img.py")
mainForm.plus.oncommand = function(id,event){
	judge = 1
	py3.main.get_img(py3.export(mainForm))
	mainForm.plus.text = ''
}

搜索

py3.exec($"\res\search.py")
mainForm.button2.oncommand = function(id,event){
	//var code = mainForm.edit3.text; 
	if (judge == 0 or mainForm.edit3.text == ''){
		mainForm.msgbox ("请刷新并输入验证码!")
	} elseif(mainForm.edit.text == ''){
		mainForm.msgbox ("请输入搜索内容!")
	}else{
		py3.main.searchBook(py3.export(mainForm))
		judge = 1
		readPage = 1
	}	
}

通过py3.exec($“\res\get_img.py”) 将python函数导入进工程即可as,然后通过py3.main.函数名调用函数即可,我这里直接将整个页面传给了python程序(其实就是一个类似于字典的数据,个人理解),然后便可以直接在python操作页面上的数据了,也可以只传递部分数据,然后通过获取返回值再在页面上展示。

四、打包程序

在完成了全部功能后,我们便可以将整个程序打包,然后生成独立的exe文件。我们只需要点击顶部工具栏中的发布按键,即可将其打包,具体如下。
在这里插入图片描述
最终,你将在指定路径下看到所生成的exe文件,至此,一个独立的爬取笔趣阁网站小说的程序制作完毕!!!

五、功能演示

测试功能流程:
打开界面
在这里插入图片描述
获取验证码并手动输入,同时填写需要搜索的小说名称,然后点击搜索,我这里以天蚕土豆的斗破苍穹为例演示(仅为教学参考)
在这里插入图片描述
在消息窗口返回了一堆结果,我们可以看到序号为7的正是我们想要搜索的土豆哥的斗破苍穹,于是我们在书籍编号处填入对应编号7,然后尝试在线阅读,看看是否为我们想要的那本书。
在这里插入图片描述
看到熟悉的 斗之力,三段 ,想必大家都清楚,小说获取成功了。不放心的可以点击左右两边的箭头进行翻页,查看后续章节。根据结果反馈,第二章内容也成功显示在消息窗口。
在这里插入图片描述

最后我们来测试一下下载功能。只需要输入起始和结束章节序号即可。这里我就简单下载前十章的内容试试看。
在这里插入图片描述
提示我们下载成功了,打开对应的文件夹看看。
在这里插入图片描述
OK,我们已经成功的下载了斗破苍穹前十章的内容。

全文至此,我们已经实现了最开始设定的全部功能,只不过没有做到自动识别验证码有些不完美,如果有擅长机器学习的小伙伴可以自行尝试训练模型,其实这个网站的验证码很简单的(找一个识别数码管数字的模型说不定也可以)

完结撒花~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值