假期听书友福利-(lian)(ting)(网)有声小说下载脚本

两个星期的考试周副本结束,今天放假。寝室就我一个人,闲来没事,写篇博客混混时间。好像现在csdn上爬虫主题比较火,我也来个听书网站的下载脚本吧。
(前两次投竟然审核没通过)

下载脚本

(本脚本仅限爬取该网站免费内容)

网站选取和网页元素踩点

我挺喜欢听小说的,某雅,某人听书都充过会员,但爬他们网站的资源是可能有被禁的风险,思来想去还是爬个没有版权保护的听书网站,找了一会儿,发现有个叫(lian)(ting)网的还不错。网站底下有免责声明,资源来自网络比较丰富。
并且有电脑端和手机端两个网站,非常nice

可以看一下网站的爬虫声明:
在这里插入图片描述

只要不爬取上图所写的目录,应该就不用担心。

首先观察网页整体布局

在这里插入图片描述

点击项对应的标签和属性

在这里插入图片描述

每本书对应链接应该是“https://m.ting55.com/”+href

进入选中的书籍页面,我们可以看到对应的每一集目录

在这里插入图片描述

每一集目录应该是“https://m.ting55.com/”+href

进入每一集后查看音频元素,大多为m4a和mp3格式,我们最终要找到每一集对应的音频文件地址

在类似的爬取音频视频网站时,最重要的就是找到音频视频对应的地址

选取合适的库工具

这里我使用的是Microsoft edge(浏览器)+selenium+requests+lxml(代码里面有一些库是优化使用的)

在这里插入图片描述

这个网站比较贼,如果单纯用requests库时在返回每一集的响应时会将音频资源标签去掉,所以我们需要使用selenium来将标签完整的爬取。

selenium配置资料:可以在csdn中搜索Microsoft edge+selenium,或者选择chrome+selenium来进行配置。

其他的库就正常的pip下载

开始代码部分

我们首先获取想听的书的网页信息(响应+书名)

def get_url_response(url):#传入的参数url即你想听的书的url地址
    header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'}
    Proxy={'http':'121.230.133.214:9999'}
    a=requests.get(url,proxies=Proxy,headers=header)
    return a

def get_bookname(a):
    html=etree.HTML(a.text)
    name=html.xpath('//*[@id="wrapper"]/div[3]/div/div/div[2]/div/div[2]/h1/text()')
    return name 

然后获取小说每一章的url地址

def get_page_url(reponse,start_page,stop_page):
    html=etree.HTML(reponse.text)
    page_url=[]
    for i in range(start_page,stop_page+1):
        page_url.append('https://m.ting55.com/'+html.xpath(f'/html/body/div[1]/div[3]/div/div/div[4]/div/ul/li[{i}]/a/@href')[0])
    return page_url #获取的每个章节的url地址

获取每一章的音频地址并爬取保存

@retry(stop_max_attempt_number=6) #假如该函数断开,重复尝试的次数
def get_audio_url(driver,page_url,name):
#     #声明代理
    global num
    num=num+1
    if (num==4):
        return
    print(page_url,"---第{}次".format(num))
    driver.get(page_url)
    sleep(120)
    page_all=driver.find_element_by_xpath('/html/body/div[1]/section/h1').text
    
    audio_url=driver.find_element_by_xpath('//*[@id="player"]').get_attribute("src")
    
    print("开始爬取{}".format(name))
    save(name,page_all,audio_url)

    num=0
    
def save(name,page,audio_url):
    path = f'D:/有声小说/{name}//'
    if not os.path.exists(path):
        os.makedirs(path)
    audio_content = requests.get(audio_url).content
    #audio_content=request.get(audio_url).content
    with open(path +page+ '.mp3', mode='wb') as f:
        f.write(audio_content)
        print('正在保存:', page)
        print("等待一会开始爬取下一章")
        # sleep(100)


主进程

if __name__ == '__main__':
    url='https://www.ting55.com/book/13864'
    # start=int(input("起始集:"))
    start=10
    # stop=int(input("中止集:"))
    stop=100
    proxy = Proxy({ 'proxyType': ProxyType.MANUAL, 
# #代理 ip 和端口
               'httpProxy': '223.215.118.145:9999'}) 
# #配置对象 DesiredCapabilities 
    dc=DesiredCapabilities.EDGE.copy()
# #把代理 ip 加入配置对象
    proxy.add_to_capabilities(dc) 
    option=EdgeOptions()
    option.add_argument('headless')
    option.add_argument(
    'user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36')

    option.add_experimental_option('excludeSwitches', ['enable-automation'])
    # driver=webdriver.Edge("D:/edgedriver_win64/9.1/msedgedriver.exe",capabilities=dc,options=option)
    driver = Edge("D:/edgedriver_win64/9.1/msedgedriver.exe",options = option)
    re=get_url_response(url)
    try:
        get_medio(driver,get_page_url(re,start,stop),get_bookname(re))
    except Exception as e:
        print(e,"5小时后还在被封")
        driver.close()
    print("第{}到第{}已经爬取完成".format(start,stop))
    driver.close()

完整代码

import requests
import os
from lxml import etree
# from selenium import webdriver
from time import sleep
from selenium.webdriver.common.proxy import Proxy 
from selenium.webdriver.common.proxy import ProxyType
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from retrying import retry
from msedge.selenium_tools import EdgeOptions
from msedge.selenium_tools import Edge

num = 0

def get_url_response(url):
    header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'}
    Proxy={'http':'121.230.133.214:9999'}
    a=requests.get(url,proxies=Proxy,headers=header)
    return a


def get_page_url(reponse,start_page,stop_page):
    html=etree.HTML(reponse.text)
    page_url=[]
    for i in range(start_page,stop_page+1):
        page_url.append('https://m.ting55.com/'+html.xpath(f'/html/body/div[1]/div[3]/div/div/div[4]/div/ul/li[{i}]/a/@href')[0])
    return page_url

def get_bookname(a):
    html=etree.HTML(a.text)
    name=html.xpath('//*[@id="wrapper"]/div[3]/div/div/div[2]/div/div[2]/h1/text()')
    return name 

@retry(stop_max_attempt_number=6)#假如该函数断开,重复尝试的次数
def get_audio_url(driver,page_url,name):
#     #声明代理
    global num
    num=num+1
    if (num==4):
        return
    print(page_url,"---第{}次".format(num))
    driver.get(page_url)
    sleep(120)#每一集之间的爬取设置暂停2分钟
    page_all=driver.find_element_by_xpath('/html/body/div[1]/section/h1').text
    
    audio_url=driver.find_element_by_xpath('//*[@id="player"]').get_attribute("src")
    
    print("开始爬取{}".format(name))
    save(name,page_all,audio_url)

    num=0

def get_medio(driver,page,name):
    global num
    try_num=0
    stop=0
    
    for i in page:
        get_audio_url(driver,i,name)
        stop+=1
        if(stop%4 == 0 and stop!=0):
            print("为防止爬取过快被限制,暂停10分钟")
            sleep(600)
            stop=0
#这个网站有访问限制,如果一定时间内访问过于频繁就会被封一个小时,所以我设置了上面的for循环每爬取四集就停十分钟            
        while (num>=4 and try_num<=2):
            print("开始等待一小时")#
            sleep(3600)
            print("等待时间结束,开始爬取")
            try_num=try_num+1  
            print("get_medio中{}的第{}次尝试".format(i,try_num))    
            num=0
            get_audio_url(driver,i,name)
#假如被封禁一个小时,这个while语句会自动等待一小时后再试着爬取,一直被禁则重复五次后异常退出                  
        try_num=0
        

def save(name,page,audio_url):
    path = f'D:/有声小说/{name}//'
    if not os.path.exists(path):
        os.makedirs(path)
    audio_content = get_url_response(audio_url).content
    #audio_content=request.get(audio_url).content
    with open(path +page+ '.m4a', mode='wb') as f:
        f.write(audio_content)
        print('正在保存:', page)
        print("等待一会开始爬取下一章")
        # sleep(100)

if __name__ == '__main__':
    url=input("恋听网中书籍url地址:")
    start=int(input("起始集:"))
    stop=int(input("中止集:"))
    proxy = Proxy({ 'proxyType': ProxyType.MANUAL, 
# #代理 ip 和端口
               'httpProxy': '223.215.118.145:9999'}) 
# #配置对象 DesiredCapabilities 
    dc=DesiredCapabilities.EDGE.copy()
# #把代理 ip 加入配置对象
    proxy.add_to_capabilities(dc) 
    option=EdgeOptions()
    option.add_argument('headless')
    option.add_argument(
    'user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36')

    option.add_experimental_option('excludeSwitches', ['enable-automation'])
    # driver=webdriver.Edge("D:/edgedriver_win64/9.1/msedgedriver.exe",capabilities=dc,options=option)
    driver = Edge("D:/edgedriver_win64/9.1/msedgedriver.exe",options = option)
    re=get_url_response(url)
    try:
        get_medio(driver,get_page_url(re,start,stop),get_bookname(re))
    except Exception as e:
        print(e,"5小时后还在被封")
        driver.close()
    print("第{}到第{}已经爬取完成".format(start,stop))
    driver.close()

注意:

这个脚本写的时间比较短,可能会有一些东西无法兼顾,比如防止被封禁的方法(我选择以降低速度来防止访问频繁被禁),其实可以做个代理ip池切换ip爬取。如果只是自己听小说我觉得应该够用了,建议晚上运行脚本,白天听。

觉得有帮助的朋友,能给个赞吗?求求了

本人原创,若要转载请私信通知即可

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
您好!我是 ChitGPT AI,很高兴能够为您解答问题。 针对您提出的问题,我可以给出以下解答: 对于输入的正整数 target,可以通过双指针法求出所有和为 target 的连续正整数序列。具体地,我们设两个指针 small 和 big 分别表示连续正整数序列的起点和终点,初始时两个指针都指向 1,即序列为 {1}。然后如果序列的和小于 target,我们将 big 指针右移一位,扩展序列的长度;如果序列的和大于 target,我们将 small 指针右移一位,缩小序列的长度;如果序列的和等于 target,即找到了一个符合要求的连续正整数序列,将其加入结果列表中,并将 big 指针右移一位,继续寻找下一个连续序列。 具体实现过程中,我们需要注意以下几点: 1. 如果区间和小于 target,应该扩展序列的末尾,即将 big 指针右移一位; 2. 如果区间和大于 target,应该缩小序列的开头,即将 small 指针右移一位; 3. 如果 big 指针移动到了 target 的一半位置,就没有必要再继续往下寻找了,因为后面的数肯定不符合要求。 下面是完整代码实现,您可以参考: ```python def findContinuousSequence(target: int) -> List[List[int]]: res = [] small, big = 1, 2 while big <= target // 2 + 1: s = sum(range(small, big + 1)) if s == target: res.append(list(range(small, big + 1))) big += 1 elif s < target: big += 1 else: small += 1 return res ``` 希望我的回答能对您有所帮助,如果您还有其他问题,欢迎随时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值