抓取网页生成电子书(《修真小主播》使用Scrapy抓取电子书爬虫思路怎么抓取数据 )
优采云 发布时间: 2022-01-25 01:00抓取网页生成电子书(《修真小主播》使用Scrapy抓取电子书爬虫思路怎么抓取数据
)
使用 Scrapy 抓取电子书
爬行动物的想法
如何抓取数据,首先我们需要看看从哪里获取数据,打开“小耕主播”的页面,如下:
有一个目录选项卡,单击此选项卡可以查看目录。使用浏览器的元素查看工具,我们可以找到每章的目录和相关信息。根据这些信息,我们可以爬取到特定页面:
获取章节地址
现在我们打开 xzxzb.py 文件,也就是我们刚刚创建的爬虫:
# -*- coding: utf-8 -*-
import scrapy
'''
更多Python学习资料以及源码教程资料,可以在群1136201545免费获取
'''
class XzxzbSpider(scrapy.Spider):
name = 'xzxzb'
allowed_domains = ['qidian.com']
start_urls = ['http://qidian.com/']
def parse(self, response):
pass
start_urls 是目录地址,爬虫会自动爬取这个地址,然后在后面的解析中处理结果。现在让我们编写处理目录数据的代码,首先爬取小说首页获取目录列表:
def parse(self, response):
pages = response.xpath('//div[@id="j-catalogWrap"]//ul[@class="cf"]/li')
for page in pages:
url = page.xpath('./child::a/attribute::href').extract()
print url
pass
在网页中获取 DOM 数据有两种方式,一种是使用 CSS 选择器,另一种是使用 XML 的 xPath 查询。
这里我们使用xPath,相关知识请自行学习,看上面代码,首先我们通过ID获取目录框,获取类cf获取目录列表:
pages = response.xpath('//div[@id="j-catalogWrap"]//ul[@class="cf"]/li')
接下来遍历子节点,查询li标签中a子节点的href属性,最后打印出来:
for page in pages:
url = page.xpath('./child::a/attribute::href').extract()
print url
这样,可以说爬取章节路径的小爬虫已经写好了。使用以下命令运行xzxzb爬虫查看结果:
scrapy crawl xzxzb
这时候我们的程序可能会出现如下错误:
…
ImportError: No module named win32api
…
只需运行以下语句:
pip install pypiwin32
屏幕输出如下:
> ...
> [u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/wrrduN6auIlOBDFlr9quQA2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/Jh-J5usgyW62uJcMpdsVgA2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/5YXHdBvg1ImaGfXRMrUjdw2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/fw5EBeKat-76ItTi_ILQ7A2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/KsFh5VutI6PwrjbX3WA1AA2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/-mpKJ01gPp1p4rPq4Fd4KQ2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/MlZSeYOQxSPM5j8_3RRvhw2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/5TXZqGvLi-3M5j8_3RRvhw2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/sysD-JPiugv4p8iEw--PPw2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/xGckZ01j64-aGfXRMrUjdw2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/72lHOJcgmedOBDFlr9quQA2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/cZkHZEYnPl22uJcMpdsVgA2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/vkNh45O3JsRMs5iq0oQwLQ2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/ge4m8RjJyPH6ItTi_ILQ7A2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/Y33PuxrKT4dp4rPq4Fd4KQ2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/MDQznkrkiyXwrjbX3WA1AA2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/A2r-YTzWCYj6ItTi_ILQ7A2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/Ng9CuONRKei2uJcMpdsVgA2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/Q_AxWAge14pMs5iq0oQwLQ2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/ZJshvAu8TVVp4rPq4Fd4KQ2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/hYD2P4c5UB2aGfXRMrUjdw2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/muxiWf_jpqTgn4SMoDUcDQ2']
[u'//read.qidian.com/chapter/MuRzJqCY6MyoLoerY3WDhg2/OQQ5jbADJjVp4rPq4Fd4KQ2']
> ...
爬章节路径的小爬虫写了,但是我们的目的不仅如此,我们会使用这些地址来爬取内容:
章节页面分析
接下来我们分析章节页面,我们要从中获取标题和内容。
如果说用于章节信息爬取的parser方法,那么我们可以写一个爬取每个章节内容的方法,比如:parser_chapter,先看章节页面的具体情况:
可以看到,章节的全部内容在类名main-text-wrap的div标签中,标题是类名j_chapterName的h3标签,具体内容是类名的div标签读取内容 j_readContent。
尝试打印出来:
# -*- coding: utf-8 -*-
import scrapy
class XzxzbSpider(scrapy.Spider):
name = 'xzxzb'
allowed_domains = ['qidian.com']
start_urls = ['https://book.qidian.com/info/1010780117/']
def parse(self, response):
pages = response.xpath('//div[@id="j-catalogWrap"]//ul[@class="cf"]/li')
for page in pages:
url = page.xpath('./child::a/attribute::href').extract_first()
# yield scrapy.Request('https:' + url, callback=self.parse_chapter)
yield response.follow(url, callback=self.parse_chapter)
pass
def parse_chapter(self, response):
title = response.xpath('//div[@class="main-text-wrap"]//h3[@class="j_chapterName"]/text()').extract_first().strip()
content = response.xpath('//div[@class="main-text-wrap"]//div[@class="read-content j_readContent"]').extract_first().strip()
print title
# print content
pass
上一步我们得到了一个章节地址,这是从输出内容的一个相对路径,所以我们使用了yield response.follow(url, callback=self.parse_chapter),第二个参数是一个回调函数来处理章节页面,爬取到章节页面后,我们解析页面并将标题保存到文件中。
next_page = response.urljoin(url)
yield scrapy.Request(next_page, callback=self.parse_chapter)
与使用 response.follow 不同,scrapy.Request 需要通过相对路径来构造绝对路径。Response.follow 可以直接使用相对路径,所以不需要调用 urljoin 方法。
注意response.follow直接返回一个Request实例,可以直接通过yield返回。
获取数据后,将其存储。由于我们想要一个 html 页面,我们可以按标题存储它。代码如下:
def parse_chapter(self, response):
title = response.xpath('//div[@class="main-text-wrap"]//h3[@class="j_chapterName"]/text()').extract_first().strip()
content = response.xpath('//div[@class="main-text-wrap"]//div[@class="read-content j_readContent"]').extract_first().strip()
# print title
# print content
filename = './down/%s.html' % (title)
with open(filename, 'wb') as f:
f.write(content.encode('utf-8'))
pass
到目前为止,我们已经成功捕获到我们的数据,但是它不能直接使用,需要进行排序和优化。
数据管理
首先,我们爬取的章节页面的排序不是很好,手动排列太费时间精力;另外,章节内容收录很多多余的东西,阅读体验不好,需要优化内容的排版和可读性。
我们先对章节进行排序,因为目录中的章节列表是按顺序排列的,所以只需在下载页面名称中加上序号即可。
但是保存网页的代码是一个回调函数,只有在处理目录时才能确定顺序。回调函数怎么知道顺序?因此,我们需要告诉回调函数它处理章节的序号,并且我们需要向回调函数传递参数。修改后的代码如下:
'''
更多Python学习资料以及源码教程资料,可以在群1136201545免费获取
'''
def parse(self, response):
pages = response.xpath('//div[@id="j-catalogWrap"]//ul[@class="cf"]/li')
for page in pages:
url = page.xpath('./child::a/attribute::href').extract_first()
idx = page.xpath('./attribute::data-rid').extract_first()
# yield scrapy.Request('https:' + url, callback=self.parse_chapter)
req = response.follow(url, callback=self.parse_chapter)
req.meta['idx'] = idx
yield req
pass
def parse_chapter(self, response):
idx = response.meta['idx']
title = response.xpath('//div[@class="main-text-wrap"]//h3[@class="j_chapterName"]/text()').extract_first().strip()
content = response.xpath('//div[@class="main-text-wrap"]//div[@class="read-content j_readContent"]').extract_first().strip()
# print title
# print content
filename = './down/%s_%s.html' % (idx, title)
cnt = '%s %s' % (title, content)
with open(filename, 'wb') as f:
f.write(cnt.encode('utf-8'))
pass
使用 Sigil 创建电子书
加载html文件
要制作 ePub 电子书,我们首先通过 Sigil 将抓取的文件加载到程序中,然后在“添加文件”对话框中选择所有文件:
制作目录
当文件中存在 HTML h 标签时,单击 Generate Directory 按钮自动生成目录。我们在之前的数据捕获中自动添加了 h1 标签:
做一个封面
封面本质上是HTML,可以编辑或者从页面爬取,所以我留给你自己实现。