目录
前言
最近刷到一个视频,介绍了一款没听说过的工具语言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,我们已经成功的下载了斗破苍穹前十章的内容。
全文至此,我们已经实现了最开始设定的全部功能,只不过没有做到自动识别验证码有些不完美,如果有擅长机器学习的小伙伴可以自行尝试训练模型,其实这个网站的验证码很简单的(找一个识别数码管数字的模型说不定也可以)
完结撒花~