今天我们来进行Python爬取小说网的案例,与前面学习的爬取图片和爬取电影网不同,小说网的数据量比较大,相比前两者要复杂的多。
首先分析需求,我们要对每个分类的小说进行爬取,并且进行分类,不仅是文字还有图片信息,着重考虑的是网页目录,页数跳转和下载后乱码的问题。
下面开始写代码吧!
首先导入今天的几个包
import requests
from lxml import etree
from urllib.request import urlretrieve
from urllib.parse import quote
import os
# 正则表达式:从目标字符串提取需要的字符的一种匹配规则。
import re
一部小说的全部信息需要如下代码
# 小说名称
novel_name = div.xpath('h1/text()')[0]
# 小说点击次数
novel_click_num = div.xpath('ul/li[1]/text()')[0].split(":")[-1]
# 小说文件大小
novel_size = div.xpath('ul/li[2]/text()')[0].split(":")[-1]
# 小说书籍类型
novel_file_type = div.xpath('ul/li[3]/text()')[0].split(":")[-1]
# 小说更新日期
novel_update_time = div.xpath('ul/li[4]/text()')[0].split(":")[-1]
# 小说连载状态
novel_status = div.xpath('ul/li[5]/text()')[0].split(":")[-1]
# 小说作者
novel_author = div.xpath('ul/li[6]/text()')[0].split(":")[-1]
# 小说运行环境
novel_run_envir = div.xpath('ul/li[7]/text()')[0].split(":")[-1]
# 小说最新章节
novel_last_chapter = div.xpath('ul/li[8]/a/text()')[0]
# 小说图片的地址
novel_img_url = "https://www.qisuu.la" + html_obj.xpath('//div[@class="detail_pic"]/img/@src')[0]
# 小说的下载地址
# 根据正则表达式提取
pattern_obj = re.compile(r"get_down_url.*?,'(.*?)',", re.S)
novel_download_url = re.search(pattern_obj, response.text).group(1)
全部代码:
import requests
from lxml import etree
from urllib.request import urlretrieve
from urllib.parse import quote
import os
# 正则表达式:从目标字符串提取需要的字符的一种匹配规则。
import re
# 判断是否有奇书网这个文件夹,如果没有,就创建一个并且切换进去
# 如果有则直接切换进去
if not os.path.exists("奇书网"):
os.mkdir("奇书网")
os.chdir("奇书网")
else:
os.chdir("奇书网")
# 首先对网站首页发起请求,目的是为了解析出来每个小说分类的名称和地址
response = requests.get("https://www.qisuu.la/")
html_obj = etree.HTML(response.text)
a_list = html_obj.xpath('//div[@class="nav"]/a')
# 删除首页所在的a标签
del a_list[0]
for a in a_list:
href = a.xpath("@href")[0]
text = a.xpath("text()")[0]
print("正在爬取-{}-分类小说".format(text))
# 通过分类的名称创建文件夹,保证对应的分类小说存储到对应的文件夹中
if not os.path.exists(text):
os.mkdir(text)
os.chdir(text)
else:
os.chdir(text)
# 根据每个分类的href属性值,拼接出来每个分类详细的地址
type_url = "https://www.qisuu.la" + href
# 对每个小说分类的地址发起访问
response = requests.get(type_url)
# 编写正则表达式规则,从每个小说分类首页提取该小说分类的总页数
# .*?:非贪婪匹配
pattern_obj = re.compile(r"页次:1/(.*?) 每页", re.S)
# 根据正则表达式匹配规则,从页面源代码中提取总页数
total_num = re.search(pattern_obj, response.text).group(1)
# 正则表达式匹配到的total_num是一个字符串,所有需要用int转换一下
for page_num in range(1, int(total_num) + 1):
print("正在爬取第{}页小说".format(page_num))
if not os.path.exists("第{}页".format(page_num)):
os.mkdir("第{}页".format(page_num))
os.chdir("第{}页".format(page_num))
else:
os.chdir("第{}页".format(page_num))
# 在小说分类地址的基础上,拼接出来每一页小说的地址
every_page_url = type_url + "index_{}.html".format(page_num)
# 对每一页小说发起访问
response = requests.get(every_page_url)
html_obj = etree.HTML(response.text)
# 解析出来每一本小说的地址
a_list = html_obj.xpath('//div[@class="listBox"]/ul/li/a')
for a in a_list:
href = a.xpath("@href")[0]
text = a.xpath("text()")[0]
print("正在爬取-{}-小说".format(text))
if not os.path.exists(text):
os.mkdir(text)
os.chdir(text)
else:
os.chdir(text)
# 拼接出来每一本小说的地址,然后发起访问
every_novel_url = "https://www.qisuu.la" + href
response = requests.get(every_novel_url)
response.encoding = "utf-8"
html_obj = etree.HTML(response.text)
div = html_obj.xpath('//div[@class="detail_right"]')[0]
# 小说名称
novel_name = div.xpath('h1/text()')[0]
# 小说点击次数
novel_click_num = div.xpath('ul/li[1]/text()')[0].split(":")[-1]
# 小说文件大小
novel_size = div.xpath('ul/li[2]/text()')[0].split(":")[-1]
# 小说书籍类型
novel_file_type = div.xpath('ul/li[3]/text()')[0].split(":")[-1]
# 小说更新日期
novel_update_time = div.xpath('ul/li[4]/text()')[0].split(":")[-1]
# 小说连载状态
novel_status = div.xpath('ul/li[5]/text()')[0].split(":")[-1]
# 小说作者
novel_author = div.xpath('ul/li[6]/text()')[0].split(":")[-1]
# 小说运行环境
novel_run_envir = div.xpath('ul/li[7]/text()')[0].split(":")[-1]
# 小说最新章节
novel_last_chapter = div.xpath('ul/li[8]/a/text()')[0]
# 小说图片的地址
novel_img_url = "https://www.qisuu.la" + html_obj.xpath('//div[@class="detail_pic"]/img/@src')[0]
# 小说的下载地址
# 根据正则表达式提取
pattern_obj = re.compile(r"get_down_url.*?,'(.*?)',", re.S)
novel_download_url = re.search(pattern_obj, response.text).group(1)
print("没有转换之前的小说地址:", novel_download_url)
# 从小说下载地址中把其中的文字部分取出来,使用quote对文字部分内容进行编码
novel_download_url = novel_download_url.replace(novel_download_url.split("/")[-1].split(".")[0],
quote(novel_download_url.split("/")[-1].split(".")[0]))
print("转换过后的下载地址是:", novel_download_url)
# 下载小说图片
urlretrieve(novel_img_url, "{}.jpg".format(novel_name))
# 由于使用urlretrieve进行文件下载的时候,下载地址中不能含有中文,需要进行对中文进行转换
urlretrieve(novel_download_url, "{}.txt".format(novel_name))
f = open("{}信息.txt".format(novel_name), "w", encoding="utf-8")
# write():文件写入
f.write("小说名称:{}".format(novel_name))
f.write("\n")
f.write("点击次数:{}".format(novel_click_num))
f.write("\n")
f.write("文件大小:{}".format(novel_size))
f.write("\n")
f.write("书籍类型:{}".format(novel_file_type))
f.write("\n")
f.write("更新日期:{}".format(novel_update_time))
f.write("\n")
f.write("连载状态:{}".format(novel_status))
f.write("\n")
f.write("小说作者:{}".format(novel_author))
f.write("\n")
f.write("运行环境:{}".format(novel_run_envir))
f.write("\n")
f.write("最新章节:{}".format(novel_last_chapter))
f.write("\n")
f.write("图片地址:{}".format(novel_img_url))
f.write("\n")
f.write("下载地址:{}".format(novel_download_url))
f.write("\n")
print("文件关闭")
# 关闭文件
f.close()
os.chdir(os.pardir)
os.chdir(os.pardir)
os.chdir(os.pardir)
运行程序后,
我这里网路比较卡,只下载了一本就停止运行了 ,如果想下载全部,耐心等待就好了,489页 每页25本,太多了。哈哈 运行完后去你程序的源文件就可以看到奇书网文件夹了,好看的小说就都在里面啦!