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

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

文章目录

  • 下载脚本
      • (本脚本仅限爬取该网站免费内容)
    • 网站选取和网页元素踩点
      • 首先观察网页整体布局
    • 选取合适的库工具
      • selenium配置资料:可以在csdn中搜索Microsoft edge+selenium,或者选择chrome+selenium来进行配置。
    • 开始代码部分
      • 我们首先获取想听的书的网页信息(响应+书名)
      • 然后获取小说每一章的url地址
      • 获取每一章的音频地址并爬取保存
      • 主进程
    • 完整代码
    • 注意:

下载脚本

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

网站选取和网页元素踩点

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

可以看一下网站的爬虫声明:
假期听书友福利-(lian)(ting)(网)有声小说下载脚本_第1张图片

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

首先观察网页整体布局

假期听书友福利-(lian)(ting)(网)有声小说下载脚本_第2张图片

点击项对应的标签和属性

假期听书友福利-(lian)(ting)(网)有声小说下载脚本_第3张图片

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

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

假期听书友福利-(lian)(ting)(网)有声小说下载脚本_第4张图片

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

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

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

选取合适的库工具

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

假期听书友福利-(lian)(ting)(网)有声小说下载脚本_第5张图片

这个网站比较贼,如果单纯用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爬取。如果只是自己听小说我觉得应该够用了,建议晚上运行脚本,白天听。

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

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

你可能感兴趣的:(python学习,python,爬虫,selenium,edge)