Python爬虫之爬取最新更新的小说网站

 更新时间:2021年05月06日 16:17:33   作者:LaoYuanPython  
这篇文章主要介绍了Python爬虫之爬取最新更新的小说网站,文中有非常详细的代码示例,对正在学习python爬虫的小伙伴们有非常好的帮助,需要的朋友可以参考下

一、引言

这个五一假期自驾回老家乡下,家里没装宽带,用手机热点方式访问网络。这次回去感觉4G信号没有以前好,通过百度查找小说最新更新并打开小说网站很慢,有时要打开好多个网页才能找到可以正常打开的最新更新。为了躲懒,老猿决定利用Python爬虫知识,写个简单应用自己查找小说最新更新并访问最快的网站,花了点时间研究了一下相关报文,经过近一天时间研究和编写,终于搞定,下面就来介绍一下整个过程。

二、关于相关访问请求及应答报文

2.1、百度搜索请求

我们通过百度网页的搜索框进行搜索时,提交的url请求是这样的:

https://www.baidu.com/s?wd=搜索词&pn=10&rn=50

请求的url为https://www.baidu.com/s,带三个参数:

  • wd:搜索的关键词
  • pn:当前需要显示搜索结果记录在总搜索结果的序号,如总搜索有300条记录满足要求,现在要求显示第130条记录,则pn参数值设为130即可
  • rn:每页显示记录数,缺省为10条,可以自行设定,但如果设定超过50,则会强制显示为每页10条。

2.2、百度返回搜索结果

百度返回的搜索结果有多种方式确定,老猿认为如下方式最简单:
以搜索小说《青萍》为例来看其中的一个返回记录:

<h3 class="t"><a data-click="{
			'F':'778317EA',
			'F1':'9D73F1E4',
			'F2':'4CA6DE6B',
			'F3':'54E5243F',
			'T':'1620130755',
			'y':'FE7FF57A'}" 
			href="http://www.baidu.com/link?url=9LLa46B6hp69vJdLx6wOGfBpoS7BaRe8zV3oSNj_Vc2AxuU0Tz5Bl7CZlqNPobdw_BElAgaadA_HfCJMtADpyq" rel="external nofollow"  target="_blank">
			<em>青萍</em>最新章节,<em>青萍</em>免费阅读 - 大神小说网</a>
			</h3>

整个搜索返回的结果在一个h3的标签内,返回的搜索结果对应url在a标签内,具体url由href来指定。这里返回的url实际上是一个百度重定向的地址,可以通过打开该url访问对应网站,并通过返回响应消息获取真正网站的URL。

2.3、小说网站关于最新更新的展现及html报文格式

根据老猿分析,约占30%的小说网站关于最新更新章节的展现类似如下:

在这里插入图片描述

首先有类似“最新章节”或“最新更新”或“最近更新”等类似提示词,在该提示词后是显示最新章节的章节序号及章节名的一个链接,对应的报文类似如下:

<p>最新章节:<a href="/book/12/12938/358787.html" rel="external nofollow"  target="_blank">第729章 就是给你们看看的</a></p>

这个报文的特点是:

“最新章节”的文本信息与小说最新章节的链接在同一个父标签内。另外需要说明的是返回的章节url并不是绝对地址,而是小说网站的相对地址。

老猿对搜索小说查找最新章节都是基于以上格式的,因此实际上程序最终获取的小说网站只占了整个搜索结果的30%左右,不过对于看小说来说已经足够了。

三、实现思路及代码

3.1、根据url获取网站名

def getHostName(url):
    httpPost = url[10:]
    hostName = url[:10]+httpPost.split('/')[0]
    return hostName

3.2、根据百度返回搜索结果地址打开网站获取小说信息

基于2.3部分介绍的小说网站返回内容,我们来根据百度返回搜索结果的URL来打开对应小说网站,并计算从请求发起到响应返回的时间:

def getNoteInfo(url):
    """
    打开指定小说网页URL获取最新章节信息
    url:百度搜索结果指定的搜索匹配记录的url
    返回该URL对应的章节ID、打开耗时、网站真正URL、网站主机名、章节相对url、章节名
    
    """
    head = mkhead()
    start = time.time_ns()
    req = urllib.request.Request(url=url, headers=head)
    try:
        resp = urllib.request.urlopen(req,timeout=2)
        #根据响应头获取真正的网页URL对应的网站名
        hostName = getHostName(resp.url)
        text = resp.read()
        #网页编码有2种:utf-8和GBK
        pageText = text.decode('utf-8')
    except UnicodeDecodeError:
        pageText =  text.decode('GBK')
    except Exception as  e:
        errInf = f"打开网站 {url} 失败,异常原因:\n{e}\n" + '\n' + traceback.format_exc() + '\n'
        logPag(errInf, False)
        return None

    #最新章节的HTML报文类似: '<p>最新章节:<a href="/html/107018/122306672.html" rel="external nofollow" >第672章 天之关梁</a></p>'
    end = time.time_ns()
    soup = BeautifulSoup(pageText, 'lxml')
    # 根据最新章节的提示信息搜索最新章节
    result = soup.find_all(string=re.compile(r'最新更新[::]|最新章节[::]|最近更新[::]|最新[::]'))
    found = False
    for rec in result:
        recP = rec.parent
        pa = recP.a
        matchs = re.match(r'(?:最新更新|最新章节|最近更新|最新)[::]第(.+)章(.+)', recP.text)
        if not matchs:return None
        groups = matchs.groups()
        if matchs and pa is not None:
            found = True
            chapter = toInt(groups[0]) #章节序号
            chapterName = groups[1] #章节名
            chaperUrl = pa.attrs['href'] #章节相对URL
            break
    if not found:
        return None

    cost = (end - start) / 1000000  #网页打开耗时计算
    return (chapter,cost,resp.url,hostName,chaperUrl,chapterName)

注意:由于不同网站访问响应情况不一样,因此在打开网页时设定超时是很有必要的,这样可以避免访问缓慢的网站耽误整体访问时间。

3.3、获取小说网页绝对url地址

将返回信息中相对url和网站名结合拼凑网页的绝对url地址:

def getChapterUrl(noteInf):
    chapter, cost, url, hostName, chaperUrl, chapterName = noteInf
    if chaperUrl.strip().startswith('http'):return chaperUrl
    elif chaperUrl.strip().startswith('/'):return hostName.strip()+chaperUrl.strip()
    else:return hostName.strip()+'/'+chaperUrl.strip()

3.4、计算排序权重

根据搜索小说网页访问的信息计算排序权重,确保最新章节排在最前,相同章节访问速度最快网站排在最前。

def noteWeight(n):
#入参n为小说信息元组: chapter, cost, url, hostName, chaperUrl, chapterName
    ch,co = n[:2]
    w = ch * 100000 + min(99999, 100000 / co)
    return w

3.5、进行百度搜索并解析搜索结果访问小说网站最新更新

根据搜索词在百度执行搜索,并取最新章节且访问速度最快的前5个网站url进行输出:

def BDSearchUsingChrome(inputword,maxCount=150):
    """
    输出相关搜索结果中具有最新章节且访问速度最快的前5个网站url
    :param word: 搜索关键词,如小说名、小说名+作者名等
    :param maxCount: 最多处理的搜索记录数
    :return: None
    """
    #百度请求url类似:https://www.baidu.com/s?wd=青萍&pn=10&rn=50
    rn = 50 #每页50条记录
    #构建请求头模拟本机谷歌浏览器访问百度网页
    head = mkheadByHostForChrome('baidu.com')
    word =  urllib.parse.quote(inputword)
    urlPagePre = 'https://www.baidu.com/s?wd='+word+'&rn=50&'
    pageCount = int(0.999+maxCount/rn)
    validNoteInf = []
    seq = 0
    logPag("开始执行搜索...")
    for page in range(pageCount):
        pn = rn*page
        urlPage = urlPagePre+str(pn)
        pageReq = urllib.request.Request(url=urlPage, headers=head)
        pageResp = urllib.request.urlopen(pageReq,timeout=2)
        pageText = pageResp.read().decode()

        if pageResp.status == 200:
            soup = BeautifulSoup(pageText,'lxml')
            links = soup.select('h3.t a[href^="http://www.baidu.com/link?url="]')

            for l in links:
                noteInf = getNoteInfo(l.attrs['href'])
                seq += 1
                if noteInf is None:
                    #print(seq,'、',l.attrs['href'],None)
                    logPag(f"{seq}、{l.attrs['href']}:查找最新章节失败,忽略",True)
                else:
                    logPag(f"{seq}、返回小说信息: {noteInf}",True)
                    #chapter,cost,url,hostName,chaperUrl,chapterName = noteInf
                    validNoteInf.append(noteInf)
    validNoteInf.sort(key=noteWeight,reverse=True)
    print(f"小说: {inputword} 最新更新访问最快的5个网站是:")
    for l in validNoteInf[:5]:#输出相关搜索结果中具有最新章节且访问速度最快的前5个网站url
        print(f"{validNoteInf.index(l)+1}、第{l[0]}章 {l[-1]}  {getChapterUrl(l)}  ,网页打开耗时 {l[1]} 毫秒")
    input("按回车键退出!")

四、搜索案例

以搜索月关大大的青萍作为案例,执行搜索的语句为:

BDSearchUsingChrome('青萍月关',150)

执行结果:

小说: 青萍月关 最新更新访问最快的5个网站是:
1、第688章  东边日出西边雨  http://www.huaxiaci.com/41620/37631250.html  ,网页打开耗时 262.0 毫秒
2、第688章  东边日出西边雨  http://www.huaxiaci.com/41620/37631250.html  ,网页打开耗时 278.0 毫秒
3、第688章  东边日出西边雨  http://www.huaxiaci.com/41620/37631250.html  ,网页打开耗时 345.5 毫秒
4、第688章  东边日出西边雨  https://www.24kwx.com/book/9/9202/8889236.html  ,网页打开耗时 774.0 毫秒
5、第688章  东边日出西边雨  https://www.27kk.net/9526/2658932.html  ,网页打开耗时 800.5 毫秒
按回车键退出!

五、小结

本文介绍了使用Python搜索指定小说最新更新章节以及访问最快网站的实现思想和关键应用代码,实现自动搜索小说最新更新章节以及获取访问最快的网站。以上的实现由于已经获取最新章节的链接,再稍微改进,就可以直接将最新章节下载到本地观看。

到此这篇关于Python爬虫之爬取最新更新的小说网站的文章就介绍到这了,更多相关Python爬取最新更新的小说网站内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Matplotlib绘图基础之配置参数详解

    Matplotlib绘图基础之配置参数详解

    Matplotlib 提供了大量配置参数,这些参数可以但不限于让我们从整体上调整通过 Matplotlib 绘制的图形样式,下面我们就来看看如何巧妙的运用这些参数吧
    2023-08-08
  • 基于Python绘制520表白代码

    基于Python绘制520表白代码

    这周五就是520,大家都准备好送给女朋友的礼物了吗?快来利用Python编写个表白代码送给她吧!文中示例代码讲解详细,跟随小编一起动手试一试吧
    2022-05-05
  • python定向爬取淘宝商品价格

    python定向爬取淘宝商品价格

    这篇文章主要为大家详细介绍了python定向爬取淘宝商品价格,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • Python 根据日志级别打印不同颜色的日志的方法示例

    Python 根据日志级别打印不同颜色的日志的方法示例

    这篇文章主要介绍了Python 根据日志级别打印不同颜色的日志的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • Python实现图像几何变换

    Python实现图像几何变换

    这篇文章主要介绍了Python实现图像几何变换的方法,实例分析了Python基于Image模块实现图像翻转、旋转、改变大小等操作的相关技巧,非常简单实用,需要的朋友可以参考下
    2015-07-07
  • python threading模块的使用指南

    python threading模块的使用指南

    python的thread模块是底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用。本文详细的讲述了threading模块的用法
    2021-06-06
  • Python实现查找数组中任意第k大的数字算法示例

    Python实现查找数组中任意第k大的数字算法示例

    这篇文章主要介绍了Python实现查找数组中任意第k大的数字算法,涉及Python针对数组的排序、查找等相关操作技巧,需要的朋友可以参考下
    2019-01-01
  • python使用urllib模块开发的多线程豆瓣小站mp3下载器

    python使用urllib模块开发的多线程豆瓣小站mp3下载器

    对豆瓣音乐小站页面html分析出所有mp3(正则匹配)文件url,然后用urllib.urlretrieve中方法直接将文件下载到本地,通过多线程技术下载
    2014-01-01
  • Python的f-string使用技巧

    Python的f-string使用技巧

    Python很早就引入了一种称为 f-string 的字符串格式化方法,它代表格式化字符串字面值,本文主要介绍了Python的f-string使用技巧,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • Python实现功能全面的学生管理系统

    Python实现功能全面的学生管理系统

    这篇文章主要为大家详细介绍了Python实现功能全面的学生管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05

最新评论