国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

編寫Python腳本抓取網(wǎng)絡(luò)小說來制作自己的閱讀器

2019-11-25 17:05:05
字體:
供稿:網(wǎng)友

你是否苦惱于網(wǎng)上無法下載的“小說在線閱讀”內(nèi)容?或是某些文章的內(nèi)容讓你很有收藏的沖動,卻找不到一個下載的鏈接?是不是有種自己寫個程序把全部搞定的沖動?是不是學(xué)了 python,想要找點(diǎn)東西大展拳腳,告訴別人“哥可是很牛逼的!”?那就讓我們開始吧! 哈哈~
    好吧,我就是最近寫 Yii 寫多了,想找點(diǎn)東西調(diào)劑一下.... = =

    本項(xiàng)目以研究為目的,所有版權(quán)問題我們都是站在作者的一邊,以看盜版小說為目的的讀者們請自行面壁!
    說了這么多,我們要做的就是把小說正文的內(nèi)容從網(wǎng)頁上爬下來,我們的研究對象是全本小說網(wǎng)....再次聲明,不對任何版權(quán)負(fù)責(zé)....
    一開始先做最基礎(chǔ)的內(nèi)容,就是把某一章的內(nèi)容抓取下來。

    環(huán)境:Ubuntu, Python 2.7

    基礎(chǔ)知識
    這個程序涉及到的知識點(diǎn)有幾個,在這里列出來,不詳細(xì)講,有疑問的直接百度會有一堆的。
    1.urllib2 模塊的 request 對像來設(shè)置 HTTP 請求,包括抓取的 url,和偽裝瀏覽器的代理。然后就是 urlopen 和 read 方法,都很好理解。
    2.chardet 模塊,用于檢測網(wǎng)頁的編碼。在網(wǎng)頁上抓取數(shù)據(jù)很容易遇到亂碼的問題,為了判斷網(wǎng)頁是 gtk 編碼還是 utf-8 ,所以用 chardet 的 detect 函數(shù)進(jìn)行檢測。在用 Windows 的同學(xué)可以在這里 http://download.csdn.net/detail/jcjc918/8231371 下載,解壓到 python 的 lib 目錄下就好。
    3. decode 函數(shù)將字符串從某種編碼轉(zhuǎn)為 unicode 字符,而 encode 把 unicode 字符轉(zhuǎn)為指定編碼格式的字符串。
     4. re 模塊正則表達(dá)式的應(yīng)用。search 函數(shù)可以找到和正則表達(dá)式對應(yīng)匹配的一項(xiàng),而 replace 則是把匹配到的字符串替換。

    思路分析:
    我們選取的 url 是 http://www.quanben.com/xiaoshuo/0/910/59302.html,斗羅大陸的第一章。你可以查看網(wǎng)頁的源代碼,會發(fā)現(xiàn)只有一個 content 標(biāo)簽包含了所有章節(jié)的內(nèi)容,所以可以用正則把 content 的標(biāo)簽匹配到,抓取下來。試著把這一部分內(nèi)容打印出來,會發(fā)現(xiàn)很多 <br /> 和  ,<br /> 要替換成換行符,   是網(wǎng)頁中的占位符,即空格,替換成空格就好。這樣一章的內(nèi)容就很美觀的出來了。完整起見,同樣用正則把標(biāo)題爬下來。

    程序

# -*- coding: utf-8 -*-  import urllib2 import re import chardet   class Book_Spider:    def __init__(self):     self.pages = []    # 抓取一個章節(jié)   def GetPage(self):     myUrl = "http://www.quanben.com/xiaoshuo/0/910/59302.html";     user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'     headers = { 'User-Agent' : user_agent }     request = urllib2.Request(myUrl, headers = headers)     myResponse = urllib2.urlopen(request)     myPage = myResponse.read()      #先檢測網(wǎng)頁的字符編碼,最后統(tǒng)一轉(zhuǎn)為 utf-8     charset = chardet.detect(myPage)     charset = charset['encoding']     if charset == 'utf-8' or charset == 'UTF-8':       myPage = myPage     else:       myPage = myPage.decode('gb2312','ignore').encode('utf-8')     unicodePage = myPage.decode("utf-8")      try:       #抓取標(biāo)題       my_title = re.search('<h1>(.*?)</h1>',unicodePage,re.S)       my_title = my_title.group(1)     except:       print '標(biāo)題 HTML 變化,請重新分析!'       return False          try:       #抓取章節(jié)內(nèi)容       my_content = re.search('<div.*?id="htmlContent" class="contentbox">(.*?)<div',unicodePage,re.S)       my_content = my_content.group(1)     except:       print "內(nèi)容 HTML 變化,請重新分析!"       return False          #替換正文中的網(wǎng)頁代碼     my_content = my_content.replace("<br />","/n")     my_content = my_content.replace(" "," ")      #用字典存儲一章的標(biāo)題和內(nèi)容     onePage = {'title':my_title,'content':my_content}     return onePage     # 用于加載章節(jié)   def LoadPage(self):     try:       # 獲取新的章節(jié)       myPage = self.GetPage()              if myPage == False:         print '抓取失?。?         return False              self.pages.append(myPage)     except:       print '無法連接服務(wù)器!'    #顯示一章   def ShowPage(self,curPage):       print curPage['title']       print curPage['content']    def Start(self):     print u'開始閱讀....../n'     #把這一頁加載進(jìn)來     self.LoadPage()     # 如果self的pages數(shù)組中存有元素     if self.pages:       nowPage = self.pages[0]       self.ShowPage(nowPage)   #----------- 程序的入口處 ----------- print u""" ---------------------------------------   程序:閱讀呼叫轉(zhuǎn)移   版本:0.1   作者:angryrookie   日期:2014-07-05   語言:Python 2.7   功能:按下回車瀏覽章節(jié) --------------------------------------- """  print u'請按下回車:' raw_input() myBook = Book_Spider() myBook.Start() 

程序運(yùn)行完在我這里可是很好看的,不信請看:^_^

理所當(dāng)然地,接下來我們要把整本小說都爬下來。首先,我們要把程序從原來的讀完一章就結(jié)束,改成讀完一章之后可以繼續(xù)進(jìn)行下一章的閱讀。
    注意到每個小說章節(jié)的網(wǎng)頁下面都有下一頁的鏈接。通過查看網(wǎng)頁源代碼,稍微整理一下(  不顯示了),我們可以看到這一部分的 HTML 是下面這種格式的:

<div id="footlink">  <script type="text/javascript" charset="utf-8" src="/scripts/style5.js"></script>  <a >上一頁</a>    <a >返回目錄</a>    <a >下一頁</a> </div> 

     上一頁 、返回目錄、下一頁都在一個 id 為 footlink  的 div 中,如果想要對每個鏈接進(jìn)行匹配的話,會抓取到網(wǎng)頁上大量的其他鏈接,但是 footlink 的 div 只有一個??!我們可以把這個 div 匹配到,抓下來,然后在這個抓下來的 div  里面再匹配 <a> 的鏈接,這時(shí)就只有三個了。只要取最后一個鏈接就是下一頁的 url 的,用這個 url 更新我們抓取的目標(biāo) url ,這樣就能一直抓到下一頁。用戶閱讀邏輯為每讀一個章節(jié)后,等待用戶輸入,如果是 quit 則退出程序,否則顯示下一章。

     基礎(chǔ)知識:
     上一篇的基礎(chǔ)知識加上 Python 的 thread 模塊.

     源代碼:

# -*- coding: utf-8 -*-  import urllib2 import re import thread import chardet  class Book_Spider:    def __init__(self):     self.pages = []     self.page = 1     self.flag = True     self.url = "http://www.quanben.com/xiaoshuo/10/10412/2095096.html"    # 將抓取一個章節(jié)   def GetPage(self):     myUrl = self.url     user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'     headers = { 'User-Agent' : user_agent }     req = urllib2.Request(myUrl, headers = headers)     myResponse = urllib2.urlopen(req)     myPage = myResponse.read()      charset = chardet.detect(myPage)     charset = charset['encoding']     if charset == 'utf-8' or charset == 'UTF-8':       myPage = myPage     else:       myPage = myPage.decode('gb2312','ignore').encode('utf-8')     unicodePage = myPage.decode("utf-8")      # 找出 id="content"的div標(biāo)記     try:       #抓取標(biāo)題       my_title = re.search('<h1>(.*?)</h1>',unicodePage,re.S)       my_title = my_title.group(1)     except:       print '標(biāo)題 HTML 變化,請重新分析!'       return False          try:       #抓取章節(jié)內(nèi)容       my_content = re.search('<div.*?id="htmlContent" class="contentbox">(.*?)<div',unicodePage,re.S)       my_content = my_content.group(1)     except:       print "內(nèi)容 HTML 變化,請重新分析!"       return False          my_content = my_content.replace("<br />","/n")     my_content = my_content.replace(" "," ")      #用字典存儲一章的標(biāo)題和內(nèi)容     onePage = {'title':my_title,'content':my_content}      try:       #找到頁面下方的連接區(qū)域       foot_link = re.search('<div.*?class="chapter_Turnpage">(.*?)</div>',unicodePage,re.S)       foot_link = foot_link.group(1)       #在連接的區(qū)域找下一頁的連接,根據(jù)網(wǎng)頁特點(diǎn)為第三個       nextUrl = re.findall(u'<a.*?href="(.*?)".*?>(.*?)</a>',foot_link,re.S)       nextUrl = nextUrl[2][0]       # 更新下一次進(jìn)行抓取的鏈接       self.url = nextUrl     except:       print "底部鏈接變化,請重新分析!"       return False      return onePage    # 用于加載章節(jié)   def LoadPage(self):     while self.flag:       if(len(self.pages) - self.page < 3):         try:           # 獲取新的頁面           myPage = self.GetPage()            if myPage == False:             print '抓取失敗!'             self.flag = False                  self.pages.append(myPage)         except:           print '無法連接網(wǎng)頁!'           self.flag = False    #顯示一章   def ShowPage(self,curPage):       print curPage['title']       print curPage['content']       print "/n"       user_input = raw_input("當(dāng)前是第 %d 章,回車讀取下一章或者輸入 quit 退出:" % self.page)       if(user_input == 'quit'):         self.flag = False       print "/n"    def Start(self):     print u'開始閱讀....../n'      # 新建一個線程     thread.start_new_thread(self.LoadPage,())      # 如果self的page數(shù)組中存有元素     while self.flag:       if self.page <= len(self.pages):         nowPage = self.pages[self.page-1]         self.ShowPage(nowPage)         self.page += 1      print u"本次閱讀結(jié)束"   #----------- 程序的入口處 ----------- print u""" ---------------------------------------   程序:閱讀呼叫轉(zhuǎn)移   版本:0.2   作者:angryrookie   日期:2014-07-07   語言:Python 2.7   功能:按下回車瀏覽下一章節(jié) --------------------------------------- """  print u'請按下回車:' raw_input(' ') myBook = Book_Spider() myBook.Start() 

現(xiàn)在這么多小說閱讀器,我們只需要把我們要的小說抓取到本地的 txt 文件里就好了,然后自己選個閱讀器看,怎么整都看你了。

    其實(shí)上個程序我們已經(jīng)完成了大部分邏輯,我們接下來的改動只需要把抓取到每一章的時(shí)候不用顯示出來,而是存入 txt 文件之中。另外一個是程序是不斷地根據(jù)下一頁的 Url 進(jìn)行抓取的,那么什么時(shí)候結(jié)束呢?注意當(dāng)?shù)竭_(dá)小說的最后一章時(shí)下一頁的鏈接是和返回目錄的鏈接是一樣的。所以我們抓取一個網(wǎng)頁的時(shí)候就把這兩個鏈接拿出來,只要出現(xiàn)兩個鏈接一樣的時(shí)候,就停止抓取。最后就是我們這個程序不需要多線程了,我們只要一個不斷在抓取小說頁面的線程就行了。
    不過,小說章節(jié)多一點(diǎn)時(shí)候,等待完成的時(shí)間會有點(diǎn)久。目前就不考慮這么多了,基本功能完成就 OK....

    基礎(chǔ)知識:前面的基礎(chǔ)知識 - 多線程知識 + 文件操作知識。

     源代碼:

# -*- coding:utf-8 -*-  import urllib2 import urllib import re import thread import chardet  class Book_Spider:    def __init__(self):     self.pages = []     self.page = 1     self.flag = True     self.url = "http://www.quanben.com/xiaoshuo/0/910/59302.html"    # 將抓取一個章節(jié)   def GetPage(self):     myUrl = self.url     user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'     headers = { 'User-Agent' : user_agent }     req = urllib2.Request(myUrl, headers = headers)     myResponse = urllib2.urlopen(req)     myPage = myResponse.read()      charset = chardet.detect(myPage)     charset = charset['encoding']     if charset == 'utf-8' or charset == 'UTF-8':       myPage = myPage     else:       myPage = myPage.decode('gb2312','ignore').encode('utf-8')     unicodePage = myPage.decode("utf-8")      # 找出 id="content"的div標(biāo)記     try:       #抓取標(biāo)題       my_title = re.search('<h1>(.*?)</h1>',unicodePage,re.S)       my_title = my_title.group(1)     except:       print '標(biāo)題 HTML 變化,請重新分析!'       return False          try:       #抓取章節(jié)內(nèi)容       my_content = re.search('<div.*?id="htmlContent" class="contentbox">(.*?)<div',unicodePage,re.S)       my_content = my_content.group(1)     except:       print "內(nèi)容 HTML 變化,請重新分析!"       return False          my_content = my_content.replace("<br />","/n")     my_content = my_content.replace(" "," ")      #用字典存儲一章的標(biāo)題和內(nèi)容     onePage = {'title':my_title,'content':my_content}      try:       #找到頁面下方的連接區(qū)域       foot_link = re.search('<div.*?class="chapter_Turnpage">(.*?)</div>',unicodePage,re.S)       foot_link = foot_link.group(1)       #在連接的區(qū)域找下一頁的連接,根據(jù)網(wǎng)頁特點(diǎn)為第三個       nextUrl = re.findall(u'<a.*?href="(.*?)".*?>(.*?)</a>',foot_link,re.S)       #目錄鏈接       dir_url = nextUrl[1][0]       nextUrl = nextUrl[2][0]       # 更新下一次進(jìn)行抓取的鏈接       self.url = nextUrl        if(dir_url == nextUrl):         self.flag = False                return onePage     except:       print "底部鏈接變化,請重新分析!"       return False    # 用于加載章節(jié)   def downloadPage(self):      f_txt = open(u"斗羅大陸.txt",'w+')     while self.flag:       try:         # 獲取新的頁面         myPage = self.GetPage()                  if myPage == False:             print '抓取失?。?             self.flag = False          title = myPage['title'].encode('utf-8')         content = myPage['content'].encode('utf-8')          f_txt.write(title + '/n/n')         f_txt.write(content)         f_txt.write('/n/n/n')          print "已下載 ",myPage['title']        except:         print '無法連接服務(wù)器!'         self.flag = False              f_txt.close()    def Start(self):     print u'開始下載....../n'      self.downloadPage()       print u"下載完成"   #----------- 程序的入口處 ----------- print u""" ---------------------------------------   程序:閱讀呼叫轉(zhuǎn)移   版本:0.3   作者:angryrookie   日期:2014-07-08   語言:Python 2.7   功能:按下回車開始下載 --------------------------------------- """  print u'請按下回車:' raw_input(' ') myBook = Book_Spider() myBook.Start() 

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 杭锦旗| 浦城县| 仪征市| 镇雄县| 博客| 辛集市| 大兴区| 迁安市| 松溪县| 尤溪县| 玉山县| 遵义市| 琼结县| 视频| 涿州市| 南部县| 赞皇县| 黑水县| 方城县| 桐城市| 金湖县| 乌拉特前旗| 海原县| 根河市| 安西县| 桐柏县| 靖远县| 永胜县| 金堂县| 任丘市| 微山县| 巢湖市| 濮阳县| 临邑县| 龙游县| 黔江区| 吉安市| 平凉市| 林西县| 西林县| 湾仔区|