使用Python爬取喜欢的小说后在本地存储为txt文件

使用Python爬取喜欢的小说后在本地存储为txt文件

最近在看小说时因为是在手机上在线观看,百度了半天也没找到可以下载的txt全集,实在没办法只好借助python来帮我完成需求!
准备爬取的小说名称 萧阳叶云舒
目标小说网站 https://www.ly990.com/

准备工具:pycharm
chrome 谷歌浏览器(其它浏览器亦可,谷歌最佳)
python3.7 环境

依赖第三方包: requests BeautifulSoup
如果没有requests包

pip install requests

pip install beautifulsoup4

第一步:先获取所有章节以及所有章节的链接
按F12即可出现开发者界面
使用Python爬取喜欢的小说后在本地存储为txt文件_第1张图片
第二步:刷新界面后,点击Network
![图2

第二步:在浏览器捕捉的众多需求中,除去js,图片等就找到了目标请求,如下图所示
![图3
可以看到该请求响应的html文件中 可以拿到所有 章节,以及每个章节的子链接
现在问题是我们想要的章节都是在html文件中,如何处理呢?没关系,python中的强大的解析库
BeautifulSoup为我们指明了方向
有关BeautifulSoup不懂的同学可以参考下这篇博文链接
https://blog.csdn.net/qq_36119192/article/details/82952442

我们点开其中一个章节并再次捕捉请求,就可以获得他的请求url:https://www.ly990.com/7_7349/10769168.html;
发现是get请求,该url可以发现是 https://www.ly990.com 和 /7_7349/10769168.html 拼接而成,而/7_7349/10769168.html 就是我们第二步中图片所示的html网页中的信息。我们还可以看看get请求请求头中所需要的信息,其中的path,user-agent:信息需要关注
![图4-1
使用Python爬取喜欢的小说后在本地存储为txt文件_第2张图片
接下来整理思路 我们只要获取所有的章节以及所有章节的子链接,然后我们循环去请求每个章节(请求头中需要设置path,user-agent等),然后以追加的方式进行写入不就可以实现完整小说的爬取了么?
话不多收直接上代码

代码如下

# coding:utf-8

import re
import os
import time
import random
import requests

from bs4 import BeautifulSoup


def get_contents():
    # 请求头
    headers = {'authority': 'www.ly990.com',
               'method': 'GET',
               'path': '/7_7349/',
               'scheme': 'https',
               'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,'
                         'image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
               'accept-encoding': 'gzip, deflate, br',
               'accept-language': 'zh-CN,zh;q=0.9',
               'referer': 'https://www.ly990.com/7_7349/5975618.html',
               'upgrade-insecure-requests': '1',
               'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                             "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
               }
    fix_url = "https://www.ly990.com"
    url = fix_url + "/7_7349/"
    mysession = requests.session()
    # 获取带有所有章节目录的响应
    response = mysession.get(url=url, headers=headers)
    # 用BeautifulSoup库解析html文件,获取soup对象
    soup = BeautifulSoup(response.content.decode(encoding="gbk"), "lxml")
    # soup对象根据"dd"标签即可获取所有的章节
    res_list = soup.select("dd")
    return res_list


if __name__ == '__main__':
    # 调用获取所有章节
    res_list = get_contents()
    # user-agent列表
    user_agent_list = ['Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko',
                       'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                       'Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3696.400 SLBrowser/10.0.3740.400',
                       'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                       'Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763']
    # 请求每一章节时所使用的请求头
    headers = {'authority': 'www.ly990.com',
               'method': 'GET',
               'path': '/7_7349/',
               'scheme': 'https',
               'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,'
                         'image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
               'accept-encoding': 'gzip, deflate, br',
               'accept-language': 'zh-CN,zh;q=0.9',
               'upgrade-insecure-requests': '1',
               'user-agent': ""
               }
    # 从章节列表中循环每一个章节进行请求
    for item in res_list:
        # soup中的string属性可以直接获取a标签文字
        content_name = item.a.string
        # soup中的href属性可以直接获取a标签包含的链接
        href_content = item.a['href']
        # 更新请求头中的path字段信息
        headers.update({'path': href_content})
        # 简单的反爬虫策略,每次随机选择一个user-agent来作为请求头,让服务器以为是不同的浏览器
        headers.update({'user-agent': random.choice(user_agent_list)})
        try:
            # 组合形成最终的章节url
            print("url is %s" % ("https://www.ly990.com" + href_content))
            # 发送get请求  超市时间设为20秒
            resopnse = requests.get(url=("https://www.ly990.com" + href_content), headers=headers, timeout=20)
        except Exception as e:
            print(e)
            # 发生超时后随即选择user-agent再次发送请求
            headers.update({'user-agent': random.choice(user_agent_list)})
            print("发生异常,url是%s" % ("https://www.ly990.com" + href_content))
            # 间隔 5-8秒后发送请求(避免被服务器发现请求过于频繁)
            time.sleep(random.choice([5, 6, 7, 8]))
            resopnse = requests.get(url=("https://www.ly990.com" + href_content), headers=headers, timeout=20)
        # 判断请求状态
        if resopnse.status_code not in [200, "200"]:
            print("the status is %s" % resopnse.status_code)
            # 如果状态不是200说明请求过于频繁应休息5分钟后再开始
            time.sleep(300)
            # 下面的try--except是为了再次请求之前请求失败的url(状态码不是200try:
                print("url is %s" % ("https://www.ly990.com" + href_content))
                resopnse = requests.get(url=("https://www.ly990.com" + href_content), headers=headers, timeout=20)
            except Exception as e:
                headers.update({'user-agent': random.choice(user_agent_list)})
                print("发生异常,url是%s" % ("https://www.ly990.com" + href_content))
                time.sleep(random.choice(range(10, 30)))
                resopnse = requests.get(url=("https://www.ly990.com" + href_content), headers=headers, timeout=20)
        # 对于正常拿到章节内容后的响应利用BeautifulSoup获取soup对象
        one_soup = BeautifulSoup(resopnse.content.decode(encoding="gbk"), "lxml")
        # 利用find_all方法获取文字内容并将一些不需要的字符进行置空处理
        real_content = str(one_soup.find_all(attrs={'id': 'content'})[0]).replace(" ", "").replace("
"
, ""). \ replace(r'', "").replace(", "").replace("
", "").replace(r"</p>", "") # 在本地打开test2.txt文件来存储爬取到的小说内容 with open("test2.txt", "a+", encoding='utf-8') as f: # 写入章节目录 f.write(str("\n" + content_name + "\n")) # 写入章节内容 f.write(real_content.replace("\n", "")) # 为了避免请求过于频繁 尽可能降低请求频率 time.sleep(random.choice(range(10, 50)))

运行效果

使用Python爬取喜欢的小说后在本地存储为txt文件_第3张图片

查看爬取到的test2.txt文件

使用Python爬取喜欢的小说后在本地存储为txt文件_第4张图片

查看test2.txt文件内容

使用Python爬取喜欢的小说后在本地存储为txt文件_第5张图片

你可能感兴趣的:(使用Python爬取喜欢的小说后在本地存储为txt文件)