使用Python爬取喜欢的小说后在本地存储为txt文件
            最近在看小说时因为是在手机上在线观看,百度了半天也没找到可以下载的txt全集,实在没办法只好借助python来帮我完成需求!
            
             准备爬取的小说名称 
            
              萧阳叶云舒
            
            
             目标小说网站 https://www.ly990.com/
          
            准备工具:pycharm
            
             chrome 谷歌浏览器(其它浏览器亦可,谷歌最佳)
            
             python3.7 环境
          
            依赖第三方包: requests BeautifulSoup
            
             如果没有requests包
          
pip install requests
pip install beautifulsoup4
            第一步:先获取所有章节以及所有章节的链接
            
             按F12即可出现开发者界面
            
            
              
            
            
             第二步:刷新界面后,点击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
            
            
              
            
            
             接下来整理思路 我们只要获取所有的章节以及所有章节的子链接,然后我们循环去请求每个章节(请求头中需要设置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(状态码不是
              
                200
              
              )
            
              
                try
              
              
                :
              
              
                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
              
              
                )
              
              
                )
              
              
                )
              
            
          
          运行效果
查看爬取到的test2.txt文件
查看test2.txt文件内容

