抓取网页生成电子书(如何用Python爬取网页制作电子书思路怎么抓取数据?)

优采云 发布时间: 2021-09-20 00:07

  抓取网页生成电子书(如何用Python爬取网页制作电子书思路怎么抓取数据?)

  作者简介:孙震,软件工程师,长期从事企业信息系统的研发工作。他主要擅长后台业务功能的设计和开发

  本文来自作者在gitchat上分享的主题“如何用Python抓取网页以制作电子书”。用scrapy抓取电子书

  爬行动物思维

  首先,我们需要看看从哪里获得数据。打开秀珍小锚页面,如下图:

  

  有一个目录选项卡。单击此选项卡以查看目录。使用浏览器的元素查看工具,我们可以找到每个章节的目录和相关信息。根据这些信息,我们可以爬到特定页面:

  

  获取章节地址

  现在我们打开xzxzb.py文件,它是我们刚刚创建的爬虫程序:

  # -*- coding: utf-8 -*-

import scrapy

class XzxzbSpider(scrapy.Spider):

name = 'xzxzb'

allowed_domains = ['qidian.com']

start_urls = ['http://qidian.com/']

def parse(self, response):

pass

  start_uuURL是目录地址。爬虫程序将自动爬网此地址,并在下面的解析中处理结果。现在,让我们编写代码来处理目录数据。首先,爬上小说的主页以获取目录列表:

   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标记中查询子节点的href属性,最后将其打印出来:

  for page in pages:

url = page.xpath('./child::a/attribute::href').extract()

print url

  这样,可以说爬行章节路径的小爬虫已经被编写好了。使用以下命令运行xzzb crawler以查看结果:

  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_uuChapter,首先查看章节页面的详细信息:

  

  您可以看到,本章的全部内容都在div标记中,类名为main text wrap,标题是类名为J_u,是chaptername的H3标记。具体内容是类名为readcontent的readcontent J_uDiv标记

  请尝试将此打印出来:

  # -*- 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不同,绝对路径需要通过相对路径构建。Response.follow可以直接使用相对路径,因此不需要调用urljoin方法

  请注意,response.follow直接返回一个请求实例,该实例可以通过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

  到目前为止,我们已成功捕获数据,但无法直接使用。需要对其进行分类和优化

  数据排序

  首先,我们爬下来的章节和页面的排序不是很好。如果我们手工安排,需要花费太多的时间和精力;另外,章节内容收录很多附加内容,阅读体验不好。我们需要优化内容的排版和可读性

  让我们先把章节排好。因为目录中的章节列表是按顺序排列的,所以我们只需要在下载页面的名称中添加一个序列号

  但是保存网页的代码是一个回调函数。只有在处理目录时才能确定顺序。回调函数如何知道顺序?因此,我们需要告诉回调函数处理部分的序列号。我们需要将参数传递给回调函数。修改后的代码如下:

   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,可以从页面编辑或爬网。让我们让您自己来实现它

  

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线