爬取《The Hitchhiker’s Guide to Python!》python進階書並製成pdf

sergiojune發表於2019-03-02

這是日常學python的第15篇原創文章

前幾篇文章我們學習了requests庫和正則,還有個urllib庫,我上篇文章也用了requests庫來教大家去爬那些返回json格式的網頁,挺好玩的。有讀者讓我來個正則的,所以我今天就來個正則+requests來進行爬取。

今天原來是想爬小說的,但想到我不怎麼看小說,讀者也是都喜歡學習的,對吧?嘻嘻!所以我來爬個與python相關的內容,恰好前幾天我又看到別人推薦的一本python進階書,這本書的作者是我們的python大神kennethreitz徵集各路愛好python的人所寫的,下面是地址:

中文版:pythonguidecn.readthedocs.io/zh/latest/

英文版:docs.python-guide.org/en/latest/

這本書適合於一切有python的學習者,不管你是初入python的小白,還是熟練使用python的老手,都適用。但是不看也沒有影響你學習爬蟲哈,這個只是說些python的奇淫技巧。

由於這本書在網上只有英語的電子版,可我英語渣渣,所以爬箇中文版的網頁然後把他弄成電子版。

若想直接獲取該書電子版,可以在公眾號「日常學python」後臺回覆『進階』直接獲取。

本篇文章用到的工具如下:

  • requests庫

  • 正規表示式

  • Sigil:將html網頁轉成epub電子書

  • epub轉pdf:http://cn.epubee.com/epub轉pdf.html

好了,下面詳細分析:

1
分析網站內容

爬取《The Hitchhiker’s Guide to Python!》python進階書並製成pdf

可以看到首頁中有整本書的內容連結,所以可以直接爬首頁獲取整本書的連結。

熟練地按下f12檢視網頁請求,非常容易找到這個爬取《The Hitchhiker’s Guide to Python!》python進階書並製成pdf

請求網站為:pythonguidecn.readthedocs.io/zh/latest/

請求方式為get,狀態碼為200,而且返回的是html元素,所以我們可以用正則來匹配所需要的內容。

那看看我們的匹配內容所在的地方

爬取《The Hitchhiker’s Guide to Python!》python進階書並製成pdf

可以看到這個內容的地址和內容標題都在這個a標籤上,所以正則很容易,如下:

toctree-l1.*?reference internal" href="([^"]*?)">(.*?)</a>
複製程式碼

不知道你的正則學得怎樣了,這裡還是簡單說下:

  • .:這個是概括字符集,為匹配除換行符以外的任意字元

  • *:這個是數量詞,匹配的次數為0次以上

  • ?:加了這個問號表示非貪婪,一般預設為貪婪

  • [^"]:這個表示不匹配雙引號,挺好用的

實在不記得的可以看看我這篇文章,這裡不詳細說了,不記得就點開爬蟲必學知識之正規表示式下篇看看

這裡需要注意的是:在這裡獲取的網址列表裡面有個內容的導航,如下:image.png

所有我們在匹配完之後還需要再將這些帶#號的網址給過濾掉。

接下來的就是獲取每個網頁的內容

爬取《The Hitchhiker’s Guide to Python!》python進階書並製成pdf

可以看到內容都在這個div標籤內,所以和上面一樣,用正則就可以獲取了。

ps: 其實這裡用BeautifulSoup更好用,我會在後面文章中講到哈!

匹配內容的正則為:

section".*?(<h1>.*?)<div class="sphinxsidebar
複製程式碼

因為我的那個工具是把這些內容的html下載下來就可以了,所以接下來不需要清洗裡面的html元素。

內容分析完畢,接下來的就容易了,就是用個迴圈把遍歷所有文章,然後就利用正則把他爬下來就可以了。

2
實操部分
import re, requests

class Spider(object):
   def __init__(self, headers, url):
       self.headers = headers
       self.url = url

   def __get_hrefs(self):
       '''獲取書本的所有連結'''
       response = requests.get(self.url, self.headers)
       if response.status_code == 200:
           response.encoding = 'utf-8'
           hrefs = re.findall('toctree-l1.*?reference internal" href="([^"]*?)">(.*?)</a>', response.text, re.S)
           return hrefs
       else:
           print('訪問書本內容失敗,狀態碼為', response.status_code)

   def __get_page(self, url):
       '''獲取首頁'''
       response = requests.get(url, self.headers)
       response.encoding = 'utf-8'
       content = re.findall('section".*?(<h1>.*?)<div class="sphinxsidebar', response.text, re.S)
       return content[0]

   def __get_content(self, href):
       '''獲取每個頁面的內容'''
       if href:
           href = self.url + href
           response = requests.get(href, self.headers)
           response.encoding = 'utf-8'
           content = re.findall('section".*?(<h1>.*?)<div class="sphinxsidebar', response.text, re.S)
           if content:
               return content[0]
           else:
               print('正則獲取失敗')
       else:
           print('獲取內容失敗')

   def run(self):
       '''迴圈獲取整本書內容'''
       self.num = 0
       hrefs = self.__get_hrefs()
       content = self.__get_page(self.url)
       with open(str(self.num)+'Python最佳實踐指南.html', 'w', encoding='utf-8') as f:
           f.write(content)
           print('寫入目錄成功')
       for href, title in hrefs:
           if "#" in href:
               continue
           self.num += 1
           content = self.__get_content(href)
           with open(str(self.num)+title+'.html', 'w', encoding='utf-8') as f:
               f.write(content)
               print('下載第'+str(self.num)+'章成功')
       print('下載完畢')


def main():
   url = 'http://pythonguidecn.readthedocs.io/zh/latest/'
   headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36'}
   spider = Spider(headers, url)
   spider.run()


if __name__ == '__main__':
   main()
複製程式碼

點選執行,感覺美滋滋,可惜啊,程式碼總是愛玩弄你,趕緊報了個錯:

  File "E:/anaconda/python_project/newspaper/spider.py", line 52, in run
   with open(str(self.num)+title+'.html', 'w', encoding='utf-8') as f:
FileNotFoundError: [Errno 2] No such file or directory: '38與C/C++庫互動.html'
複製程式碼

一眼看下去,還挺鬱悶的,我沒有開啟檔案的,都是在寫檔案,為什麼報了這個錯?仔細一看報錯內容,這個名字有問題啊,你看

38與C/C++庫互動.html
複製程式碼

這個在window系統是以為你在 38與C 的 C++庫互動.html 下的,怪不得會報錯,所以,我在這裡加了這個程式碼把/給替換掉image.png

3
把內容整成pdf

點選Sigil 的 + 號把剛才下載的內容匯入

爬取《The Hitchhiker’s Guide to Python!》python進階書並製成pdf爬取《The Hitchhiker’s Guide to Python!》python進階書並製成pdf

生成目錄

爬取《The Hitchhiker’s Guide to Python!》python進階書並製成pdf

新增書名作者

爬取《The Hitchhiker’s Guide to Python!》python進階書並製成pdf

新增封面:點選左上角的 工具 -> 新增封面 即可

點選儲存即可完成

轉pdf:cn.epubee.com/epub轉pdf.ht…

這個很容易就不說了。

結語

好了,文章內容就這麼多,下個文章就是學習新內容了。期待ing。

上述文章如有錯誤歡迎在留言區指出,如果這篇文章對你有用,點個贊,轉個發如何?

MORE
延伸閱讀

◐◑老司機帶你用python來爬取妹子圖

◐◑ python爬蟲常用庫之requests詳解

◐◑ 爬蟲必學知識之正規表示式下篇


1802109804.png

日常學python

程式碼不止bug,還有美和樂趣

相關文章