Python爬蟲中文小說網點查找小說並且保存到txt(含中文亂碼處理方法)
從某些網站看小說的時候經常出現垃圾廣告,一氣之下寫個爬蟲,把小說鏈接抓取下來保存到txt,用requests_html全部搞定,代碼簡單,容易上手.
中間遇到最大的問題就是編碼問題,第一抓取下來的小說內容保持到txt時出現亂碼,第二url編碼問題,第三UnicodeEncodeError
先貼源代碼,後邊再把思路還有遇到的問題詳細說明。
from requests_html import HTMLSession as hs def get_story(url): global f session=hs() r=session.get(url,headers=headers) r.html.encoding=‘GBK‘ title=list(r.html.find(‘title‘))[0].text#獲取小說標題 nr=list(r.html.find(‘.nr_nr‘))[0].text#獲取小說內容 nextpage=list(r.html.find(‘#pb_next‘))[0].absolute_links#獲取下一章節絕對鏈接 nextpage=list(nextpage)[0] if(nr[0:10]=="_Middle();"): nr=nr[11:] if(nr[-14:]==‘本章未完,點擊下一頁繼續閱讀‘): nr=nr[:-15] print(title,r.url) f.write(title) f.write(‘\n\n‘) f.write(nr) f.write(‘\n\n‘) return nextpage def search_story(): global BOOKURL global BOOKNAME haveno=[] booklist=[] bookname=input("請輸入要查找的小說名:\n") session=hs() payload={‘searchtype‘:‘articlename‘,‘searchkey‘:bookname.encode(‘GBK‘),‘t_btnsearch‘:‘‘} r=session.get(url,headers=headers,params=payload) haveno=list(r.html.find(‘.havno‘))#haveno有值,則查找結果如果為空 booklist=list(r.html.find(‘.list-item‘))#booklist有值,則有多本查找結果 while(True): if(haveno!=[] and booklist==[]): print(‘Sorry~!暫時沒有搜索到您需要的內容!請重新輸入‘) search_story() break elif(haveno==[] and booklist!=[]): print("查找到{}本小說".format(len(booklist))) for book in booklist: print(book.text,book.absolute_links) search_story() break else: print("查找到結果,小說鏈接:",r.url) BOOKURL=r.url BOOKNAME=bookname break global BOOKURL global BOOKNAME url=‘http://m.50zw.net/modules/article/waps.php‘ headers = { ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 OPR/53.0.2907.99‘ } search_story() chapterurl=BOOKURL.replace("book","chapters") session=hs() r=session.get(chapterurl,headers=headers) ch1url=list(r.html.find(‘.even‘))[0].absolute_links#獲取第一章節絕對鏈接 ch1url=list(ch1url)[0] global f f=open(BOOKNAME+‘.txt‘, ‘a‘,encoding=‘gb18030‘,errors=‘ignore‘) print("開始下載,每一章節都需要爬到,速度快不了,請等候。。。。\n") nextpage=get_story(ch1url) while(nextpage!=BOOKURL): nextpage=get_story(nextpage) f.close
爬蟲思路及遇到的問題分析如下:
先查找小說,並且把小說鏈接抓取下來,以網站http://m.50zw.net/modules/article/waps.php為例,首先在瀏覽器中打開鏈接並且右鍵點檢查,選擇Network標簽,我用的是chrome瀏覽器,按F1設置把Network底下的Preserve log勾選上,方便接下來查找log,以搜索‘帝後世無雙’為例,搜索到結果後直接跳到了此本小說的url:http://m.50zw.net/book_86004/
查看到請求方式是GET,Request URL是 http://m.50zw.net/modules/article/waps.php?searchtype=articlename&searchkey=%B5%DB%BA%F3%CA%C0%CE%DE%CB%AB&t_btnsearch=
然後分析出請求參數有三個,searchtype先固定用圖書名來查找,而searchkey我們輸入的是”敵後世無雙“,url encoding成了%B5%DB%BA%F3%CA%C0%CE%DE%CB%AB,我們在python ide裏邊分別輸入:
"敵後世無雙".encode(‘GBK‘):b‘\xb5\xd0\xba\xf3\xca\xc0\xce\xde\xcb\xab‘
"敵後世無雙".encode(‘utf-8‘):b‘\xe6\x95\x8c\xe5\x90\x8e\xe4\xb8\x96\xe6\x97\xa0\xe5\x8f\x8c‘
對照輸出結果我們知道這裏url編碼采用的是GBK
接下來我們用代碼來驗證我們分析的結果
from requests_html import HTMLSession as hs url=‘http://m.50zw.net/modules/article/waps.php‘ payload={‘searchtype‘:‘articlename‘,‘searchkey‘:‘帝後世無雙‘,‘t_btnsearch‘:‘‘} headers = { ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36 OPR/53.0.2907.99‘ } session=hs() r=session.get(url,headers=headers,params=payload) print(r.url)
運行結果:
http://m.50zw.net/modules/article/waps.php?searchtype=articlename&searchkey=%E5%B8%9D%E5%90%8E%E4%B8%96%E6%97%A0%E5%8F%8C&t_btnsearch=
比較得到的url跟我們剛才手動輸入後得到的url有出入,代碼裏邊如果沒有指定編碼格式的話了這裏url編碼默認是urf-8,因為編碼問題我們沒有得到我們想要的結果,那接下來我們修改代碼指定編碼試試
payload={‘searchtype‘:‘articlename‘,‘searchkey‘:‘帝後世無雙‘.encode(‘GBK‘),‘t_btnsearch‘:‘‘}
這回運行結果得到我們想要的url:
http://m.50zw.net/book_86004/
好,成功了!!!
那接下來我們要獲取第一章節的鏈接,中間用到了requests_html來抓取絕對鏈接
bookurl=‘http://m.50zw.net/book_86004/‘ chapterurl=bookurl.replace("book","chapters") session=hs() r=session.get(chapterurl,headers=headers) ch1url=list(r.html.find(‘.even‘))[0].absolute_links ch1url=list(ch1url)[0] print(ch1url)
運行結果:
http://m.50zw.net/book_86004/26127777.html
成功取得第一章節鏈接
接下來我們開始獲取小說內容並且獲取下一章鏈接直到把整本小說下載下來為止,
在這個部分遇到UnicodeEncodeError: ‘gbk‘ codec can‘t encode character ‘\xa0‘ in position 46:illegal multibyte sequence,這個問題最終在用open函數打開txt時加兩個參數解決encoding=‘gb18030‘,errors=‘ignore‘.
在之前也用過另外一種方案,就是把u‘\xa0‘替換成跟它等效的u‘ ‘,雖然解決了‘\xa0‘的error,可是後來又出現了’\xb0‘的error,總不能出現一個類似的rror就修改代碼替換一次,所以這個方案被放棄掉.
session=hs() r=session.get(ch1url,headers=headers) title=list(r.html.find(‘title‘))[0].text nr=list(r.html.find(‘.nr_nr‘))[0].text ##nr=nr.replace(u‘\xa0‘,u‘ ‘) nextpage=list(r.html.find(‘#pb_next‘))[0].absolute_links nextpage=list(nextpage)[0] if(nr[0:10]=="_Middle();"): nr=nr[11:] if(nr[-14:]==‘本章未完,點擊下一頁繼續閱讀‘): nr=nr[:-15] print(title,r.url) print(nextpage) f=open(‘帝後世無雙.txt‘, ‘a‘,encoding=‘gb18030‘,errors=‘ignore‘) f.write(title) f.write(‘\n\n‘) f.write(nr) f.write(‘\n\n‘)
Python爬蟲中文小說網點查找小說並且保存到txt(含中文亂碼處理方法)