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


Posted in Python onMay 06, 2021

一、引言

这个五一假期自驾回老家乡下,家里没装宽带,用手机热点方式访问网络。这次回去感觉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%的小说网站关于最新更新章节的展现类似如下:

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

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

<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爬取最新更新的小说网站内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python中用Descriptor实现类级属性(Property)详解
Sep 18 Python
详解python3实现的web端json通信协议
Dec 29 Python
python+matplotlib绘制简单的海豚(顶点和节点的操作)
Jan 02 Python
Python实现PS滤镜的旋转模糊功能示例
Jan 20 Python
解决Python网页爬虫之中文乱码问题
May 11 Python
如何利用Python开发一个简单的猜数字游戏
Sep 22 Python
Python变量、数据类型、数据类型转换相关函数用法实例详解
Jan 09 Python
python isinstance函数用法详解
Feb 13 Python
使用pymysql查询数据库,把结果保存为列表并获取指定元素下标实例
May 15 Python
结束运行python的方法
Jun 16 Python
python使用XPath解析数据爬取起点小说网数据
Apr 22 Python
python 中[0]*2与0*2的区别说明
May 10 Python
Python基础之操作MySQL数据库
Python 如何安装Selenium
Django实现在线无水印抖音视频下载(附源码及地址)
Django给表单添加honeypot验证增加安全性
Django利用AJAX技术实现博文实时搜索
May 06 #Python
python 如何获取页面所有a标签下href的值
May 06 #Python
Python中常见的导入方式总结
May 06 #Python
You might like
咖啡风味 世界咖啡主要分布分布 咖啡的生长要求
2021/03/06 新手入门
mac下Apache + MySql + PHP搭建网站开发环境
2014/06/02 PHP
PHP+Mysql树型结构(无限分类)数据库设计的2种方式实例
2014/07/15 PHP
php实现mysql数据库分表分段备份
2015/06/18 PHP
PHP实现二叉树的深度优先与广度优先遍历方法
2015/09/28 PHP
php+ajax实现带进度条的上传图片功能【附demo源码下载】
2016/09/14 PHP
php封装单文件上传到数据库(路径)
2017/10/15 PHP
PHP实现微信小程序用户授权的工具类示例
2019/03/05 PHP
jquery表单验证框架提供的身份证验证方法(示例代码)
2013/12/27 Javascript
Vuejs第十篇之vuejs父子组件通信
2016/09/06 Javascript
vue.js $refs和$emit 父子组件交互的方法
2017/12/20 Javascript
JS中实现隐藏部分姓名或者电话号码的代码
2018/07/17 Javascript
微信小程序webview与h5通过postMessage实现实时通讯的实现
2019/08/20 Javascript
Javascript如何实现双指控制图片功能
2020/02/25 Javascript
JavaScript console的使用方法实例分析
2020/04/28 Javascript
微信小程序实现发微博功能的示例代码
2020/06/24 Javascript
[57:22]完美世界DOTA2联赛PWL S2 FTD vs PXG 第二场 11.27
2020/12/01 DOTA
[01:08:29]DOTA2-DPC中国联赛定级赛 RNG vs Aster BO3第一场 1月9日
2021/03/11 DOTA
分享8个非常流行的 Python 可视化工具包
2019/06/05 Python
Pycharm pyuic5实现将ui文件转为py文件,让UI界面成功显示
2020/04/08 Python
解决pycharm导入numpy包的和使用时报错:RuntimeError: The current Numpy installation (‘D:\\python3.6\\lib\\site-packa的问题
2020/12/08 Python
澳大利亚首个在线预订旅游网站:Wotif
2017/07/19 全球购物
英国护发和美妆在线商店:Klip Shop
2019/03/24 全球购物
合作协议书格式
2014/08/19 职场文书
社区娱乐活动方案
2014/08/21 职场文书
落实八项规定专题民主生活会对照检查材料
2014/09/15 职场文书
2014党员民主评议个人思想剖析发言
2014/09/19 职场文书
领导干部四风问题自我剖析材料
2014/09/25 职场文书
2014年秘书工作总结
2014/11/25 职场文书
孔子观后感
2015/06/08 职场文书
厉行节约工作总结
2015/08/12 职场文书
《惊弓之鸟》教学反思
2016/02/20 职场文书
python b站视频下载的五种版本
2021/05/27 Python
python之PySide2安装使用及QT Designer UI设计案例教程
2021/07/26 Python
搞笑Gif:这么白这么长的腿像极了一楼的女朋友
2022/03/21 杂记
R9700摩机记
2022/04/05 无线电