Python爬蟲之爬取最新更新的小說網站
一、引言
這個五一假期自駕回老家鄉(xiāng)下,家里沒裝寬帶,用手機熱點方式訪問網絡。這次回去感覺4G信號沒有以前好,通過百度查找小說最新更新并打開小說網站很慢,有時要打開好多個網頁才能找到可以正常打開的最新更新。為了躲懶,老猿決定利用Python爬蟲知識,寫個簡單應用自己查找小說最新更新并訪問最快的網站,花了點時間研究了一下相關報文,經過近一天時間研究和編寫,終于搞定,下面就來介紹一下整個過程。
二、關于相關訪問請求及應答報文
2.1、百度搜索請求
我們通過百度網頁的搜索框進行搜索時,提交的url請求是這樣的:
https://www.baidu.com/s?wd=搜索詞&pn=10&rn=50
請求的url為https://www.baidu.com/s,帶三個參數:
- wd:搜索的關鍵詞
- pn:當前需要顯示搜索結果記錄在總搜索結果的序號,如總搜索有300條記錄滿足要求,現(xiàn)在要求顯示第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'}"
rel="external nofollow" target="_blank">
<em>青萍</em>最新章節(jié),<em>青萍</em>免費閱讀 - 大神小說網</a>
</h3>
整個搜索返回的結果在一個h3的標簽內,返回的搜索結果對應url在a標簽內,具體url由href來指定。這里返回的url實際上是一個百度重定向的地址,可以通過打開該url訪問對應網站,并通過返回響應消息獲取真正網站的URL。
2.3、小說網站關于最新更新的展現(xiàn)及html報文格式
根據老猿分析,約占30%的小說網站關于最新更新章節(jié)的展現(xiàn)類似如下:

首先有類似“最新章節(jié)”或“最新更新”或“最近更新”等類似提示詞,在該提示詞后是顯示最新章節(jié)的章節(jié)序號及章節(jié)名的一個鏈接,對應的報文類似如下:
<p>最新章節(jié):<a href="/book/12/12938/358787.html" rel="external nofollow" target="_blank">第729章 就是給你們看看的</a></p>
這個報文的特點是:
“最新章節(jié)”的文本信息與小說最新章節(jié)的鏈接在同一個父標簽內。另外需要說明的是返回的章節(jié)url并不是絕對地址,而是小說網站的相對地址。
老猿對搜索小說查找最新章節(jié)都是基于以上格式的,因此實際上程序最終獲取的小說網站只占了整個搜索結果的30%左右,不過對于看小說來說已經足夠了。
三、實現(xiàn)思路及代碼
3.1、根據url獲取網站名
def getHostName(url):
httpPost = url[10:]
hostName = url[:10]+httpPost.split('/')[0]
return hostName
3.2、根據百度返回搜索結果地址打開網站獲取小說信息
基于2.3部分介紹的小說網站返回內容,我們來根據百度返回搜索結果的URL來打開對應小說網站,并計算從請求發(fā)起到響應返回的時間:
def getNoteInfo(url):
"""
打開指定小說網頁URL獲取最新章節(jié)信息
url:百度搜索結果指定的搜索匹配記錄的url
返回該URL對應的章節(jié)ID、打開耗時、網站真正URL、網站主機名、章節(jié)相對url、章節(jié)名
"""
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
#最新章節(jié)的HTML報文類似: '<p>最新章節(jié):<a href="/html/107018/122306672.html" rel="external nofollow" >第672章 天之關梁</a></p>'
end = time.time_ns()
soup = BeautifulSoup(pageText, 'lxml')
# 根據最新章節(jié)的提示信息搜索最新章節(jié)
result = soup.find_all(string=re.compile(r'最新更新[::]|最新章節(jié)[::]|最近更新[::]|最新[::]'))
found = False
for rec in result:
recP = rec.parent
pa = recP.a
matchs = re.match(r'(?:最新更新|最新章節(jié)|最近更新|最新)[::]第(.+)章(.+)', recP.text)
if not matchs:return None
groups = matchs.groups()
if matchs and pa is not None:
found = True
chapter = toInt(groups[0]) #章節(jié)序號
chapterName = groups[1] #章節(jié)名
chaperUrl = pa.attrs['href'] #章節(jié)相對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、計算排序權重
根據搜索小說網頁訪問的信息計算排序權重,確保最新章節(jié)排在最前,相同章節(jié)訪問速度最快網站排在最前。
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、進行百度搜索并解析搜索結果訪問小說網站最新更新
根據搜索詞在百度執(zhí)行搜索,并取最新章節(jié)且訪問速度最快的前5個網站url進行輸出:
def BDSearchUsingChrome(inputword,maxCount=150):
"""
輸出相關搜索結果中具有最新章節(jié)且訪問速度最快的前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("開始執(zhí)行搜索...")
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']}:查找最新章節(jié)失敗,忽略",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]:#輸出相關搜索結果中具有最新章節(jié)且訪問速度最快的前5個網站url
print(f"{validNoteInf.index(l)+1}、第{l[0]}章 {l[-1]} {getChapterUrl(l)} ,網頁打開耗時 {l[1]} 毫秒")
input("按回車鍵退出!")
四、搜索案例
以搜索月關大大的青萍作為案例,執(zhí)行搜索的語句為:
BDSearchUsingChrome('青萍月關',150)
執(zhí)行結果:
小說: 青萍月關 最新更新訪問最快的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搜索指定小說最新更新章節(jié)以及訪問最快網站的實現(xiàn)思想和關鍵應用代碼,實現(xiàn)自動搜索小說最新更新章節(jié)以及獲取訪問最快的網站。以上的實現(xiàn)由于已經獲取最新章節(jié)的鏈接,再稍微改進,就可以直接將最新章節(jié)下載到本地觀看。
到此這篇關于Python爬蟲之爬取最新更新的小說網站的文章就介紹到這了,更多相關Python爬取最新更新的小說網站內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python基于similarities實現(xiàn)文本語義相似度計算和文本匹配搜索
similarities?實現(xiàn)了多種相似度計算、匹配搜索算法,支持文本、圖像,python3開發(fā),下面我們就來看看如何使用similarities實現(xiàn)文本語義相似度計算和文本匹配搜索吧2024-03-03
Python實現(xiàn)http接口自動化測試的示例代碼
這篇文章主要介紹了Python實現(xiàn)http接口自動化測試的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-10-10
python實現(xiàn)根據指定字符截取對應的行的內容方法
今天小編就為大家分享一篇python實現(xiàn)根據指定字符截取對應的行的內容方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10

