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实现在windows下操作word的方法
Apr 28 Python
Python基于高斯消元法计算线性方程组示例
Jan 17 Python
Python运维自动化之nginx配置文件对比操作示例
Aug 29 Python
在python 不同时区之间的差值与转换方法
Jan 14 Python
python监控进程状态,记录重启时间及进程号的实例
Jul 15 Python
python如何统计代码运行的时长
Jul 24 Python
Python中IP地址处理IPy模块的方法
Aug 16 Python
Django自带的加密算法及加密模块详解
Dec 03 Python
基于Python检测动态物体颜色过程解析
Dec 04 Python
浅谈tensorflow中dataset.shuffle和dataset.batch dataset.repeat注意点
Jun 08 Python
在CentOS7下安装Python3教程解析
Jul 09 Python
python利用faker库批量生成测试数据
Oct 15 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
PHP 高手之路(一)
2006/10/09 PHP
php 3行代码的分页算法(求起始页和结束页)
2009/10/21 PHP
wamp服务器访问php非常缓慢的解决过程
2015/07/01 PHP
laravel5创建service provider和facade的方法详解
2016/07/26 PHP
php分页查询的简单实现代码
2017/03/14 PHP
JavaScript 基础篇之运算符、语句(二)
2012/04/07 Javascript
基于jQuery的计算文本框字数的代码
2012/06/06 Javascript
JS 添加网页桌面快捷方式的代码详细整理
2012/12/27 Javascript
javascript实现淘宝幻灯片广告展示效果
2015/04/27 Javascript
js代码实现点击按钮出现60秒倒计时
2021/01/28 Javascript
js 动态添加元素(div、li、img等)及设置属性的方法
2016/07/19 Javascript
详解AngularJS跨页面传值(ui-router)
2017/08/23 Javascript
解决vue的 v-for 循环中图片加载路径问题
2018/09/03 Javascript
JS实现网站楼层导航效果代码实例
2020/06/16 Javascript
详解使用python的logging模块在stdout输出的两种方法
2017/05/17 Python
Win10下python 2.7与python 3.7双环境安装教程图解
2019/10/12 Python
django实现支付宝支付实例讲解
2019/10/17 Python
python实现吃苹果小游戏
2020/03/21 Python
Python控制台实现交互式环境执行
2020/06/09 Python
使用Keras中的ImageDataGenerator进行批次读图方式
2020/06/17 Python
python关于倒排列的知识点总结
2020/10/13 Python
python pymysql库的常用操作
2020/10/16 Python
pycharm使用技巧之自动调整代码格式总结
2020/11/04 Python
CSS3 三维变形实现立体方块特效源码
2016/12/15 HTML / CSS
俄罗斯眼镜网: optikaworld
2016/07/31 全球购物
美国领先的个性化礼品商城:Personalization Mall
2019/07/27 全球购物
一些Solaris面试题
2013/03/22 面试题
大学应届生求职简历的自我评价
2013/10/08 职场文书
夏季奶茶店创业计划书
2014/01/16 职场文书
父亲的菜园教学反思
2014/02/13 职场文书
暑假安全教育广播稿
2014/09/10 职场文书
争先创优心得体会
2014/09/12 职场文书
语文教师个人工作总结
2015/02/06 职场文书
库房管理员岗位职责
2015/02/12 职场文书
2016党校学习心得体会
2016/01/07 职场文书
python实现高效的遗传算法
2021/04/07 Python