這是平常學python的第15篇原創文章html
前幾篇文章咱們學習了requests庫和正則,還有個urllib庫,我上篇文章也用了requests庫來教你們去爬那些返回json格式的網頁,挺好玩的。有讀者讓我來個正則的,因此我今天就來個正則+requests來進行爬取。
python
今天原來是想爬小說的,但想到我不怎麼看小說,讀者也是都喜歡學習的,對吧?嘻嘻!因此我來爬個與python相關的內容,剛好前幾天我又看到別人推薦的一本python進階書,這本書的做者是咱們的python大神kennethreitz徵集各路愛好python的人所寫的,下面是地址:正則表達式
中文版:pythonguidecn.readthedocs.io/zh/latest/json
英文版:docs.python-guide.org/en/latest/app
這本書適合於一切有python的學習者,無論你是初入python的小白,仍是熟練使用python的老手,都適用。可是不看也沒有影響你學習爬蟲哈,這個只是說些python的奇淫技巧。python爬蟲
因爲這本書在網上只有英語的電子版,可我英語渣渣,因此爬箇中文版的網頁而後把他弄成電子版。ide
若想直接獲取該書電子版,能夠在公衆號「平常學python」後臺回覆『進階』直接獲取。工具
本篇文章用到的工具以下:學習
requests庫網站
正則表達式
Sigil:將html網頁轉成epub電子書
epub轉pdf:http://cn.epubee.com/epub轉pdf.html
好了,下面詳細分析:
能夠看到首頁中有整本書的內容連接,因此能夠直接爬首頁獲取整本書的連接。
熟練地按下f12查看網頁請求,很是容易找到這個
請求網站爲:pythonguidecn.readthedocs.io/zh/latest/
請求方式爲get,狀態碼爲200,並且返回的是html元素,因此咱們能夠用正則來匹配所須要的內容。
那看看咱們的匹配內容所在的地方
能夠看到這個內容的地址和內容標題都在這個a標籤上,因此正則很容易,以下:
toctree-l1.*?reference internal" href="([^"]*?)">(.*?)</a>
複製代碼
不知道你的正則學得怎樣了,這裏仍是簡單說下:
.:這個是歸納字符集,爲匹配除換行符之外的任意字符
*:這個是數量詞,匹配的次數爲0次以上
?:加了這個問號表示非貪婪,通常默認爲貪婪
[^"]:這個表示不匹配雙引號,挺好用的
實在不記得的能夠看看我這篇文章,這裏不詳細說了,不記得就點開爬蟲必學知識之正則表達式下篇看看
這裏須要注意的是:在這裏獲取的網址列表裏面有個內容的導航,以下:
全部咱們在匹配完以後還須要再將這些帶#號的網址給過濾掉。
接下來的就是獲取每一個網頁的內容
能夠看到內容都在這個div標籤內,因此和上面同樣,用正則就能夠獲取了。
ps: 其實這裏用BeautifulSoup更好用,我會在後面文章中講到哈!
匹配內容的正則爲:
section".*?(<h1>.*?)<div class="sphinxsidebar
複製代碼
由於個人那個工具是把這些內容的html下載下來就能夠了,因此接下來不須要清洗裏面的html元素。
內容分析完畢,接下來的就容易了,就是用個循環把遍歷全部文章,而後就利用正則把他爬下來就能夠了。
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 下的,怪不得會報錯,因此,我在這裏加了這個代碼把/給替換掉
點擊Sigil 的 + 號把剛纔下載的內容導入
生成目錄
添加書名做者
添加封面:點擊左上角的 工具 -> 添加封面 便可
點擊保存便可完成
轉pdf:cn.epubee.com/epub轉pdf.ht…
這個很容易就不說了。
結語
好了,文章內容就這麼多,下個文章就是學習新內容了。期待ing。
上述文章若有錯誤歡迎在留言區指出,若是這篇文章對你有用,點個贊,轉個發如何?
平常學python
代碼不止bug,還有美和樂趣