編寫Python指令碼抓取網路小說來製作自己的閱讀器

來源:互聯網
上載者:User
你是否苦惱於網上無法下載的“小說線上閱讀”內容?或是某些文章的內容讓你很有收藏的衝動,卻找不到一個下載的連結?是不是有種自己寫個程式把全部搞定的衝動?是不是學了 python,想要找點東西大展拳腳,告訴別人“哥可是很牛逼的!”?那就讓我們開始吧! 哈哈~
好吧,我就是最近寫 Yii 寫多了,想找點東西調劑一下.... = =

本項目以研究為目的,所有著作權問題我們都是站在作者的一邊,以看盜版小說為目的的讀者們請自行面壁!
說了這麼多,我們要做的就是把小說本文的內容從網頁上爬下來,我們的研究對象是全本小說網....再次聲明,不對任何著作權負責....
一開始先做最基礎的內容,就是把某一章的內容抓取下來。

環境:Ubuntu, Python 2.7

基礎知識
這個程式涉及到的知識點有幾個,在這裡列出來,不詳細講,有疑問的直接百度會有一堆的。
1.urllib2 模組的 request 對像來設定 HTTP 要求,包括抓取的 url,和偽裝瀏覽器的代理。然後就是 urlopen 和 read 方法,都很好理解。
2.chardet 模組,用於檢測網頁的編碼。在網頁上抓取資料很容易遇到亂碼的問題,為了判斷網頁是 gtk 編碼還是 utf-8 ,所以用 chardet 的 detect 函數進行檢測。在用 Windows 的同學可以在這裡 http://download.csdn.net/detail/jcjc918/8231371 下載,解壓到 python 的 lib 目錄下就好。
3. decode 函數將字串從某種編碼轉為 unicode 字元,而 encode 把 unicode 字元轉為指定編碼格式的字串。
4. re 模組Regex的應用。search 函數可以找到和Regex對應匹配的一項,而 replace 則是把匹配到的字串替換。

思路分析:
我們選取的 url 是 http://www.quanben.com/xiaoshuo/0/910/59302.html,鬥羅大陸的第一章。你可以查看網頁的原始碼,會發現只有一個 content 標籤包含了所有章節的內容,所以可以用正則把 content 的標籤匹配到,抓取下來。試著把這一部分內容列印出來,會發現很多
和  ,
要替換成分行符號,   是網頁中的預留位置,即空格,替換成空格就好。這樣一章的內容就很美觀的出來了。完整起見,同樣用正則把標題爬下來。

程式

# -*- coding: utf-8 -*-  import urllib2 import re import chardet   class Book_Spider:    def __init__(self):     self.pages = []    # 抓取一個章節   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()      #先檢測網頁的字元編碼,最後統一轉為 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:       #抓取標題       my_title = re.search('

(.*?)

',unicodePage,re.S) my_title = my_title.group(1) except: print '標題 HTML 變化,請重新分析!' return False try: #抓取章節內容 my_content = re.search('(.*?)","\n") my_content = my_content.replace(" "," ") #用字典儲存一章的標題和內容 onePage = {'title':my_title,'content':my_content} return onePage # 用於載入章節 def LoadPage(self): try: # 擷取新的章節 myPage = self.GetPage() if myPage == False: print '抓取失敗!' return False self.pages.append(myPage) except: print '無法串連伺服器!' #顯示一章 def ShowPage(self,curPage): print curPage['title'] print curPage['content'] def Start(self): print u'開始閱讀......\n' #把這一頁載入進來 self.LoadPage() # 如果self的pages數組中存有元素 if self.pages: nowPage = self.pages[0] self.ShowPage(nowPage) #----------- 程式的入口處 ----------- print u""" --------------------------------------- 程式:閱讀來電轉接 版本:0.1 作者:angryrookie 日期:2014-07-05 語言:Python 2.7 功能:按下斷行符號瀏覽章節 --------------------------------------- """ print u'請按下斷行符號:' raw_input() myBook = Book_Spider() myBook.Start()

程式運行完在我這裡可是很好看的,不信請看:^_^

理所當然地,接下來我們要把整本小說都爬下來。首先,我們要把程式從原來的讀完一章就結束,改成讀完一章之後可以繼續進行下一章的閱讀。
注意到每個小說章節的網頁下面都有下一頁的連結。通過查看網頁原始碼,稍微整理一下( 不顯示了),我們可以看到這一部分的 HTML 是下面這種格式的:

    上一頁    返回目錄    下一頁  

上一頁 、返回目錄、下一頁都在一個 id 為 footlink 的 div 中,如果想要對每個連結進行匹配的話,會抓取到網頁上大量的其他連結,但是 footlink 的 div 只有一個啊!我們可以把這個 div 匹配到,抓下來,然後在這個抓下來的 div 裡面再匹配 的連結,這時就只有三個了。只要取最後一個連結就是下一頁的 url 的,用這個 url 更新我們抓取的目標 url ,這樣就能一直抓到下一頁。使用者閱讀邏輯為每讀一個章節後,等待使用者輸入,如果是 quit 則退出程式,否則顯示下一章。

基礎知識:
上一篇的基礎知識加上 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"    # 將抓取一個章節   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標記     try:       #抓取標題       my_title = re.search('

(.*?)

',unicodePage,re.S) my_title = my_title.group(1) except: print '標題 HTML 變化,請重新分析!' return False try: #抓取章節內容 my_content = re.search('(.*?)","\n") my_content = my_content.replace(" "," ") #用字典儲存一章的標題和內容 onePage = {'title':my_title,'content':my_content} try: #找到頁面下方的串連地區 foot_link = re.search('(.*?)',unicodePage,re.S) foot_link = foot_link.group(1) #在串連的地區找下一頁的串連,根據網頁特點為第三個 nextUrl = re.findall(u'(.*?)',foot_link,re.S) nextUrl = nextUrl[2][0] # 更新下一次進行抓取的連結 self.url = nextUrl except: print "底部連結變化,請重新分析!" return False return onePage # 用於載入章節 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 '無法串連網頁!' self.flag = False #顯示一章 def ShowPage(self,curPage): print curPage['title'] print curPage['content'] print "\n" user_input = raw_input("當前是第 %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數組中存有元素 while self.flag: if self.page <= len(self.pages): nowPage = self.pages[self.page-1] self.ShowPage(nowPage) self.page += 1 print u"本次閱讀結束" #----------- 程式的入口處 ----------- print u""" --------------------------------------- 程式:閱讀來電轉接 版本:0.2 作者:angryrookie 日期:2014-07-07 語言:Python 2.7 功能:按下斷行符號瀏覽下一章節 --------------------------------------- """ print u'請按下斷行符號:' raw_input(' ') myBook = Book_Spider() myBook.Start()

現在這麼多小說閱讀器,我們只需要把我們要的小說抓取到本地的 txt 檔案裡就好了,然後自己選個閱讀器看,怎麼整都看你了。

其實上個程式我們已經完成了大部分邏輯,我們接下來的改動只需要把抓取到每一章的時候不用顯示出來,而是存入 txt 檔案之中。另外一個是程式是不斷地根據下一頁的 Url 進行抓取的,那麼什麼時候結束呢?注意當到達小說的最後一章時下一頁的連結是和返回目錄的連結是一樣的。所以我們抓取一個網頁的時候就把這兩個連結拿出來,只要出現兩個連結一樣的時候,就停止抓取。最後就是我們這個程式不需要多線程了,我們只要一個不斷在抓取小說頁面的線程就行了。
不過,小說章節多一點時候,等待完成的時間會有點久。目前就不考慮這麼多了,準系統完成就 OK....

基礎知識:前面的基礎知識 - 多線程知識 + 檔案操作知識。

原始碼:

# -*- 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"    # 將抓取一個章節   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標記     try:       #抓取標題       my_title = re.search('

(.*?)

',unicodePage,re.S) my_title = my_title.group(1) except: print '標題 HTML 變化,請重新分析!' return False try: #抓取章節內容 my_content = re.search('(.*?)","\n") my_content = my_content.replace(" "," ") #用字典儲存一章的標題和內容 onePage = {'title':my_title,'content':my_content} try: #找到頁面下方的串連地區 foot_link = re.search('(.*?)',unicodePage,re.S) foot_link = foot_link.group(1) #在串連的地區找下一頁的串連,根據網頁特點為第三個 nextUrl = re.findall(u'(.*?)',foot_link,re.S) #目錄連結 dir_url = nextUrl[1][0] nextUrl = nextUrl[2][0] # 更新下一次進行抓取的連結 self.url = nextUrl if(dir_url == nextUrl): self.flag = False return onePage except: print "底部連結變化,請重新分析!" return False # 用於載入章節 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 '無法串連伺服器!' self.flag = False f_txt.close() def Start(self): print u'開始下載......\n' self.downloadPage() print u"下載完成" #----------- 程式的入口處 ----------- print u""" --------------------------------------- 程式:閱讀來電轉接 版本:0.3 作者:angryrookie 日期:2014-07-08 語言:Python 2.7 功能:按下斷行符號開始下載 --------------------------------------- """ print u'請按下斷行符號:' raw_input(' ') myBook = Book_Spider() myBook.Start()

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.