Python爬取整本小说及一些问题处理和txt的一个应用

前言

初学Python,练习爬取一些内容。就从小说开始了,分享一下遇到的坑。

结果

先贴最后结果,替换目标网站即可爬取对应整本小说。

import random
import time
import requests
from lxml import etree

user_agent = [
    "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
    "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
    "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
    "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
    "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
    "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
    "Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10",
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)",
    "Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999",
]
# 拼接网址头部
head_url = 'http://www.xbiquge.la'
# 目标网站
target_path = 'http://www.xbiquge.la/5/5634/'
# 储存路径 后面空格必要
out_path = r'C:\Users\ZGM\Desktop\TestPack\狂神.txt'
# 地址最好用谷歌获取(通过ID获取(path)),火狐获取的可能会有问题(通过绝对路径获取(fullpath))。
html_data = '//*[@id="list"]/dl'
# 随机请求头文件
headers = {'User-Agent': random.choice(user_agent)}


# 获取所有章节地址
def get_all_urls():
    result = requests.get(target_path, headers)
    # 运行document.charset可以获取页面编码格式
    result.encoding = "UTF-8"
    # print(result.text)
    # 转换成一个对象 使用lxml必要步骤
    selector = etree.HTML(result.content)
    # 获取所有章节的地址
    url = selector.xpath(html_data + '//@href')
    return url


# 获取章节内容并按规则写入文件
def get_code(i):
    result = requests.get(i, headers)
    result.encoding = "UTF-8"
    selector = etree.HTML(result.content)
    titlePath = '//*[@id="wrapper"]/*[@class="content_read"]/*[@class="box_con"]/div[2]/h1/text()'
    title = selector.xpath(titlePath)
    text = selector.xpath('//*[@id="content"]//text()')
    with open(out_path, "a+", encoding='utf-8') as f:  # 打开文件
        # 以下为移除标题中的特殊字符
        teletext = str(title).replace(' ', '', 1)
        teletext = teletext.replace("['", '')
        teletext = teletext.replace("']", '')
        f.write(teletext + "\n\n\n")  # 写入小说内容
        # 写入章节内容
        for index in range(len(text)):
            # 前两个元素都为字符跳过
            if index < 2:
                continue
            # 后三个元素为广告语跳出
            if index >= len(text) - 3:
                break
            else:
                # 多余的换行符跳过
                if text[index] == '\r':
                    continue
                # 替换无法识别的空白字符
                txt = text[index].replace('\xa0', '')
                f.write("  " + str(txt))
        f.write('\n\n')
    print(teletext)


# 爬取整本
def get_text():
    url = get_all_urls()
    for i in url:
        url = head_url + i
        print(url)
        get_code(url)
        time.sleep(2)


#  测试单个章节的拉取情况
def get_test():
    url = 'http://www.xbiquge.la/5/5634/2833208.html'
    result = requests.get(url, headers)
    result.encoding = "UTF-8"
    selector = etree.HTML(result.content)
    titlePath = '//*[@id="wrapper"]/*[@class="content_read"]/*[@class="box_con"]/div[2]/h1/text()'
    title = selector.xpath(titlePath)
    text = selector.xpath('//*[@id="content"]//text()')
    with open(out_path, "a+", encoding='utf-8-sig') as f:  # 打开文件
        f.write(str(title) + "\n")  # 写入小说内容
        for i in text:
            i.replace('\xa0', '')
            f.write(i)


get_text()

结果展示

填坑过程

1:首先选择自己使用的工具,我使用的lxml。用法就不细说了,百度全都是。

import random
import time
import requests
from lxml import etree

2:选择一个目标网站。(仅作为学习使用)
首先我选择的对象是http://www.b5200.net/
然后在爬取的过程中出现了两个问题。
第一个:我在爬取单章节的内容时没有问题,但我爬取整本的时候部分章节返回为空。后来我添加了等待时间。依然会出现这种情况,但空章节的数量明显减少,我增加到2s仍然会出现这种情况,没有好的解决方案,本来想尝试try catch做处理。但没有找到合适的参考方案。
第二个:我发现在我爬取的结果中,有一部分是内容不全的。比如下图:
我找到个规律是爬取内容会在第一个箭头所指符号处截断。第一个问题可能也和这个相关(并没有验证)。我又翻了几本其他的书籍,并没有发现这种符号。

在这里插入图片描述这两个问题到现在仍然没有解决,希望有大佬能指点一下。这个网站的文字格式是“GBK”。

解决方案

出于学习的目的,可能从根本解决这个问题对我还是太难了,但为了实现效果。我就换了个网站http://www.xbiquge.la/
3:具体代码参考我贴的代码。
这里说一下我写代码时遇到的问题。
第一个:爬取的网站是否可用,因为有的网站你可以爬取到目标网站的全部地址,有的只能爬取到一部分地址。需要额外拼接一下。不是什么难的问题,但需要注意。

在这里插入图片描述

第二个:关于xpath的地址,我在用谷歌获取的xpath实际上是
//*[@id="wrapper"]/div[4]/div/div[2]/h1
但是始终获取不到我想要的内容。然后我尝试把div一个一个替换成*[@class=“content_read”] 这种格式(我也不清楚这是什么格式)全部替换了就可以获取到了,我又尝试还原一部分为div格式的。也可以获取到内容,原因不明。
但全都用*[@class=“content_read”] 这种格式不会有问题。
在这里插入图片描述第三个:关于获取不到内容的处理
因为在我换了爬取地址后爬取并没有出现缺失章节的问题,所以并没有处理。我也没找到关于xpath如何获取异常的用法,希望有大佬指点一下。大概就是一个如果我内容获取的有问题(类似于try catch之类获取错误信息并进行处理这种)就重新获取这个地址的内容的一个需求。

关于爬取到的内容的应用

其实只作为练习来说,爬取的内容对我一点用都没有。因为我其实并不喜欢看书,但为了不浪费资源的健康理念,我就想把它作为手机的本地书籍来读。
我平时用的是微信读书,然后有一个这个功能。

在这里插入图片描述然后把你爬的txt文件传上去就行了。
在这里插入图片描述
需要注意的一点是,尽量把章节名称处理的好看一些。因为我第一次的话,章节是这种带符号的,在微信读书里就显得很难看。另外在处理书籍内容的时候(即代码:获取章节内容并按规则写入文件部分)需要自己匹配对应的书籍。因为有的书开端没有空字段或者有一个空字段,末尾是也可能是两句广告语。需自行匹配。
在这里插入图片描述
以上。(仅作为学习交流使用)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值