前面练习了爬取单页的小说内容,之后又练习了提取整部小说的内容:
可参考:
一部小说爬取
继上次之后想试试批量爬取小说,想就接着干,找到目标网页的地址:
页面显示如下:
然后打开开发者工具,发现内容也都在相应体中,那提取数据就十分简单了,
页面的跳转的地址也很容易提取:
一段简单的代码实现跳转页面地址的提取,提取出来的地址少了协议,列表推导式完成地址的拼接:
跳转之后竟然没有直接到详情页,跳转到了点击阅读的页面:
没办法,只好再次提取中间跳转的地址:
同样也是很容易提取,地址也是不完整,列表推导式完成拼接:
请求之后终于到了列表详情页:
检查之后提取内容也是很简单,xpath直接提取,同时提取小说的名字,然后在请求小说内容页面的地址:
文本页面的内容同样使用xpath提取,并提取章节,但有两部小说的链接为空,所以就使用if判段直接跳过,否则接下来请求就会出错,同时在这一步直接实现保存,代码如下:
至此代码完成,完整代码如下:
'''
爬取17k小说网女生频道完本50-100万字的小说
'''
# 导入第三方库
import os
import requests
from lxml import etree
from fake_useragent import UserAgent
# 随机请求头
ua = UserAgent()
# 定义一个女生小说频道的类
class Nover_Women():
# 初始化对象
def __init__(self):
self.start_url = "https://www.17k.com/all/book/3_5_0_3_3_0_1_0_1.html"
self.headers = {'User-Agent': ua.random}
# 提取start_url的html
def get_html(self, url):
html = requests.get(url, headers=self.headers).content.decode()
return html
# 提取中间页的地址
def mid_page(self, html):
e = etree.HTML(html)
mid_link = e.xpath('//td[@class="td3"]/span/a/@href')
mid_link = ["https:" + i for i in mid_link]
return mid_link
# 定义中间详情页的方法
def mid_detail_page(self, mid_link):
mid_list = []
for link in mid_link:
mid_data = {}
mid_html = requests.get(url=link, headers=self.headers).content.decode()
e = etree.HTML(mid_html)
mid_detail_link = e.xpath('//dt[@class="read"]/a/@href')
mid_detail_link = ["https://www.17k.com/" + i for i in mid_detail_link]
mid_data["mid_detail_link"] = mid_detail_link
mid_list.append(mid_data)
return mid_list
# 定义最终详情页的方法
def fin_detail(self, mid_list):
for url in mid_list:
content = {}
r = requests.get(url=url["mid_detail_link"][0], headers=self.headers).content.decode()
e = etree.HTML(r)
content_page = e.xpath('//dl[@class="Volume"]/dd/a/@href')
# 判段内容页的返回值是否为空,如果为空则跳过
if len(content_page) == 0:
continue
# 提取大标题
book_name = e.xpath('//div[@class="Main List"]/h1/text()')
content["name"] = book_name
# 提取文本页的地址
content_page = ["https://www.17k.com" + i for i in content_page]
content["link"] = content_page
# 创建相应大标题的文件夹
if not os.path.exists(content["name"][0]):
os.mkdir(content["name"][0])
# 遍历循环请求内容页的地址
for content_url in content["link"]:
content_html = requests.get(url=content_url, headers=self.headers).content.decode()
e_content = etree.HTML(content_html)
# 提取章节标题
chapter = e_content.xpath('//div[@class="readAreaBox content"]/h1/text()')
chapter = chapter[0].replace('\t', '')
# 提取小说内容
text = e_content.xpath('//div[@class="p"]/p/text()')
with open(content["name"][0] + '/' + chapter + '.txt', 'w', encoding="utf-8") as f:
print("正在写入:" + content["name"][0] + ':' + chapter)
f.write(chapter)
f.write('\r\n')
for i in text:
f.write(i)
# 定义运行函数,实现主要逻辑
def run(self):
url = self.start_url
html = self.get_html(url)
mid_link = self.mid_page(html)
mid_list = self.mid_detail_page(mid_link)
self.fin_detail(mid_list)
# 程序运行接口
if __name__ == '__main__':
Novel_Spider = Nover_Women()
Novel_Spider.run()
爬取结果如下:
爬取了很多,就不一一展示了。代码仅作参考。