如何用Python爬數(shù)據(jù)次坡?(一)網(wǎng)頁(yè)抓取
你期待已久的Python網(wǎng)絡(luò)數(shù)據(jù)爬蟲教程來(lái)了。本文為你演示如何從網(wǎng)頁(yè)里找到感興趣的鏈接和說(shuō)明文字呀袱,抓取并存儲(chǔ)到Excel贸毕。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-21-45-09-792876.png)
需求
我在公眾號(hào)后臺(tái),經(jīng)骋拐裕可以收到讀者的留言明棍。
很多留言,是讀者的疑問(wèn)寇僧。只要有時(shí)間摊腋,我都會(huì)抽空嘗試解答。
但是有的留言嘁傀,乍看起來(lái)就不明所以了兴蒸。
例如下面這個(gè):
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-19-05-09-970402.png)
一分鐘后,他可能覺(jué)得不妥(大概因?yàn)橄肫饋?lái)细办,我用簡(jiǎn)體字寫文章)橙凳,于是又用簡(jiǎn)體發(fā)了一遍。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-18-43-47-865706.png)
我恍然大悟笑撞。
這位讀者以為我的公眾號(hào)設(shè)置了關(guān)鍵詞推送對(duì)應(yīng)文章功能岛啸。所以看了我的其他數(shù)據(jù)科學(xué)教程后,想看“爬蟲”專題茴肥。
不好意思坚踩,當(dāng)時(shí)我還沒(méi)有寫爬蟲文章。
而且瓤狐,我的公眾號(hào)暫時(shí)也沒(méi)有設(shè)置這種關(guān)鍵詞推送瞬铸。
主要是因?yàn)槲覒小?/p>
這樣的消息接收得多了批幌,我也能體察到讀者的需求。不止一個(gè)讀者表達(dá)出對(duì)爬蟲教程的興趣嗓节。
之前提過(guò)荧缘,目前主流而合法的網(wǎng)絡(luò)數(shù)據(jù)收集方法,主要分為3類:
- 開(kāi)放數(shù)據(jù)集下載赦政;
- API讀仁び睢;
- 爬蟲恢着。
前兩種方法桐愉,我都已經(jīng)做過(guò)一些介紹,這次說(shuō)說(shuō)爬蟲掰派。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-04-07-11-31-258650.png)
概念
許多讀者對(duì)爬蟲的定義从诲,有些混淆。咱們有必要辨析一下靡羡。
維基百科是這么說(shuō)的:
網(wǎng)絡(luò)爬蟲(英語(yǔ):web crawler)系洛,也叫網(wǎng)絡(luò)蜘蛛(spider),是一種用來(lái)自動(dòng)瀏覽萬(wàn)維網(wǎng)的網(wǎng)絡(luò)機(jī)器人略步。其目的一般為編纂網(wǎng)絡(luò)索引描扯。
這問(wèn)題就來(lái)了,你又不打算做搜索引擎趟薄,為什么對(duì)網(wǎng)絡(luò)爬蟲那么熱心呢绽诚?
其實(shí),許多人口中所說(shuō)的爬蟲(web crawler)杭煎,跟另外一種功能“網(wǎng)頁(yè)抓取”(web scraping)搞混了恩够。
維基百科上,對(duì)于后者這樣解釋:
Web scraping, web harvesting, or web data extraction is data scraping used for extracting data from websites. Web scraping software may access the World Wide Web directly using the Hypertext Transfer Protocol, or through a web browser.
看到?jīng)]有羡铲,即便你用瀏覽器手動(dòng)拷貝數(shù)據(jù)下來(lái)蜂桶,也叫做網(wǎng)頁(yè)抓取(web scraping)也切。是不是立刻覺(jué)得自己強(qiáng)大了很多扑媚?
但是,這定義還沒(méi)完:
While web scraping can be done manually by a software user, the term typically refers to automate processes implemented using a bot or web crawler.
也就是說(shuō)雷恃,用爬蟲(或者機(jī)器人)自動(dòng)替你完成網(wǎng)頁(yè)抓取工作疆股,才是你真正想要的。
數(shù)據(jù)抓下來(lái)干什么呢褂萧?
一般是先存儲(chǔ)起來(lái)押桃,放到數(shù)據(jù)庫(kù)或者電子表格中葵萎,以備檢索或者進(jìn)一步分析使用导犹。
所以唱凯,你真正想要的功能是這樣的:
找到鏈接,獲得Web頁(yè)面谎痢,抓取指定信息磕昼,存儲(chǔ)。
這個(gè)過(guò)程有可能會(huì)往復(fù)循環(huán)节猿,甚至是滾雪球票从。
你希望用自動(dòng)化的方式來(lái)完成它。
了解了這一點(diǎn)滨嘱,你就不要老盯著爬蟲不放了峰鄙。爬蟲研制出來(lái),其實(shí)是為了給搜索引擎編制索引數(shù)據(jù)庫(kù)使用的太雨。你為了抓取點(diǎn)兒數(shù)據(jù)拿來(lái)使用吟榴,已經(jīng)是大炮轟蚊子了。
要真正掌握爬蟲囊扳,你需要具備不少基礎(chǔ)知識(shí)吩翻。例如HTML, CSS, Javascript, 數(shù)據(jù)結(jié)構(gòu)……
這也是為什么我一直猶豫著沒(méi)有寫爬蟲教程的原因。
不過(guò)這兩天锥咸,看到王爍主編的一段話狭瞎,很有啟發(fā):
我喜歡講一個(gè)另類二八定律,就是付出兩成努力搏予,了解一件事的八成熊锭。
既然我們的目標(biāo)很明確,就是要從網(wǎng)頁(yè)抓取數(shù)據(jù)缔刹。那么你需要掌握的最重要能力球涛,是拿到一個(gè)網(wǎng)頁(yè)鏈接后,如何從中快捷有效地抓取自己想要的信息校镐。
掌握了它亿扁,你還不能說(shuō)自己已經(jīng)學(xué)會(huì)了爬蟲。
但有了這個(gè)基礎(chǔ)鸟廓,你就能比之前更輕松獲取數(shù)據(jù)了从祝。特別是對(duì)“文科生”的很多應(yīng)用場(chǎng)景來(lái)說(shuō),非常有用引谜。這就是賦能牍陌。
而且,再進(jìn)一步深入理解爬蟲的工作原理员咽,也變得輕松許多毒涧。
這也算“另類二八定律”的一個(gè)應(yīng)用吧。
Python語(yǔ)言的重要特色之一贝室,就是可以利用強(qiáng)大的軟件工具包(許多都是第三方提供)契讲。你只需要編寫簡(jiǎn)單的程序仿吞,就能自動(dòng)解析網(wǎng)頁(yè),抓取數(shù)據(jù)捡偏。
本文給你演示這一過(guò)程唤冈。
目標(biāo)
要抓取網(wǎng)頁(yè)數(shù)據(jù),我們先制訂一個(gè)小目標(biāo)银伟。
目標(biāo)不能太復(fù)雜你虹。但是完成它,應(yīng)該對(duì)你理解抓韧堋(Web Scraping)有幫助傅物。
就選擇我最近發(fā)布的一篇簡(jiǎn)書文章作為抓取對(duì)象好了。題目叫做《如何用《玉樹(shù)芝蘭》入門數(shù)據(jù)科學(xué)琉预?》挟伙。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-18-43-47-962316.png)
這篇文章里,我把之前的發(fā)布的數(shù)據(jù)科學(xué)系列文章做了重新組織和串講模孩。
文中包含很多之前教程的標(biāo)題和對(duì)應(yīng)鏈接尖阔。例如下圖紅色邊框圈起來(lái)的部分。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-18-43-47-927654.png)
假設(shè)你對(duì)文中提到教程都很感興趣榨咐,希望獲得這些文章的鏈接介却,并且存儲(chǔ)到Excel里,就像下面這個(gè)樣子:
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-18-43-47-936213.png)
你需要把非結(jié)構(gòu)化的分散信息(自然語(yǔ)言文本中的鏈接)块茁,專門提取整理齿坷,并且存儲(chǔ)下來(lái)。
該怎么辦呢数焊?
即便不會(huì)編程永淌,你也可以全文通讀,逐個(gè)去找這些文章鏈接佩耳,手動(dòng)把文章標(biāo)題遂蛀、鏈接都分別拷貝下來(lái),存到Excel表里面干厚。
但是李滴,這種手工采集方法沒(méi)有效率。
我們用Python蛮瞄。
環(huán)境
要裝Python所坯,比較省事的辦法是安裝Anaconda套裝。
請(qǐng)到這個(gè)網(wǎng)址下載Anaconda的最新版本挂捅。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-21-45-09-801080.png)
請(qǐng)選擇左側(cè)的 Python 3.6 版本下載安裝芹助。
如果你需要具體的步驟指導(dǎo),或者想知道Windows平臺(tái)如何安裝并運(yùn)行Anaconda命令,請(qǐng)參考我為你準(zhǔn)備的視頻教程状土。
安裝好Anaconda之后苗缩,請(qǐng)到這個(gè)網(wǎng)址下載本教程配套的壓縮包。
下載后解壓声诸,你會(huì)在生成的目錄(下稱“演示目錄”)里面看到以下三個(gè)文件。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-21-45-09-801703.png)
打開(kāi)終端退盯,用cd命令進(jìn)入該演示目錄彼乌。如果你不了解具體使用方法,也可以參考視頻教程渊迁。
我們需要安裝一些環(huán)境依賴包慰照。
首先執(zhí)行:
pip install pipenv
這里安裝的,是一個(gè)優(yōu)秀的 Python 軟件包管理工具 pipenv 琉朽。
安裝后毒租,請(qǐng)執(zhí)行:
pipenv install
看到演示目錄下兩個(gè)Pipfile開(kāi)頭的文件了嗎?它們就是 pipenv 的設(shè)置文檔箱叁。
pipenv 工具會(huì)依照它們墅垮,自動(dòng)為我們安裝所需要的全部依賴軟件包。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-21-45-09-803003.png)
上圖里面有個(gè)綠色的進(jìn)度條耕漱,提示所需安裝軟件數(shù)量和實(shí)際進(jìn)度算色。
裝好后,根據(jù)提示我們執(zhí)行:
pipenv shell
此處請(qǐng)確認(rèn)你的電腦上已經(jīng)安裝了 Google Chrome 瀏覽器螟够。
我們執(zhí)行:
jupyter notebook
默認(rèn)瀏覽器(Google Chrome)會(huì)開(kāi)啟灾梦,并啟動(dòng) Jupyter 筆記本界面:
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-21-45-09-804222.png)
你可以直接點(diǎn)擊文件列表中的第一項(xiàng)ipynb文件齿梁,可以看到本教程的全部示例代碼吊洼。
你可以一邊看教程的講解拧篮,一邊依次執(zhí)行這些代碼津畸。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-21-45-09-805922.png)
但是邻储,我建議的方法缎罢,是回到主界面下一屋,新建一個(gè)新的空白 Python 3 筆記本擎值。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-21-45-09-806907.png)
請(qǐng)跟著教程辈赋,一個(gè)個(gè)字符輸入相應(yīng)的內(nèi)容统锤。這可以幫助你更為深刻地理解代碼的含義,更高效地把技能內(nèi)化炭庙。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-21-45-09-807766.png)
準(zhǔn)備工作結(jié)束饲窿,下面我們開(kāi)始正式輸入代碼。
代碼
讀入網(wǎng)頁(yè)加以解析抓取焕蹄,需要用到的軟件包是 requests_html 逾雄。我們此處并不需要這個(gè)軟件包的全部功能,只讀入其中的 HTMLSession 就可以。
from requests_html import HTMLSession
然后鸦泳,我們建立一個(gè)會(huì)話(session)银锻,即讓Python作為一個(gè)客戶端,和遠(yuǎn)端服務(wù)器交談做鹰。
session = HTMLSession()
前面說(shuō)了击纬,我們打算采集信息的網(wǎng)頁(yè),是《如何用《玉樹(shù)芝蘭》入門數(shù)據(jù)科學(xué)钾麸?》一文更振。
我們找到它的網(wǎng)址,存儲(chǔ)到url變量名中饭尝。
url = 'http://www.reibang.com/p/85f4624485b9'
下面的語(yǔ)句肯腕,利用 session 的 get 功能,把這個(gè)鏈接對(duì)應(yīng)的網(wǎng)頁(yè)整個(gè)兒取回來(lái)钥平。
r = session.get(url)
網(wǎng)頁(yè)里面都有什么內(nèi)容呢实撒?
我們告訴Python,請(qǐng)把服務(wù)器傳回來(lái)的內(nèi)容當(dāng)作HTML文件類型處理涉瘾。我不想要看HTML里面那些亂七八糟的格式描述符知态,只看文字部分。
于是我們執(zhí)行:
print(r.html.text)
這就是獲得的結(jié)果了:
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-16-24-21-140063.png)
我們心里有數(shù)了立叛。取回來(lái)的網(wǎng)頁(yè)信息是正確的肴甸,內(nèi)容是完整的。
好了囚巴,我們來(lái)看看怎么趨近自己的目標(biāo)吧原在。
我們先用簡(jiǎn)單粗暴的方法,嘗試獲得網(wǎng)頁(yè)中包含的全部鏈接彤叉。
把返回的內(nèi)容作為HTML文件類型庶柿,我們查看 links 屬性:
r.html.links
這是返回的結(jié)果:
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-16-26-25-059092.png)
這么多鏈接啊秽浇!
很興奮吧浮庐?
不過(guò),你發(fā)現(xiàn)沒(méi)有柬焕?這里許多鏈接审残,看似都不完全。例如第一條結(jié)果斑举,只有:
'/'
這是什么東西搅轿?是不是鏈接抓取錯(cuò)誤啊富玷?
不是璧坟,這種看著不像鏈接的東西既穆,叫做相對(duì)鏈接。它是某個(gè)鏈接雀鹃,相對(duì)于我們采集的網(wǎng)頁(yè)所在域名(http://www.reibang.com)的路徑幻工。
這就好像我們?cè)趪?guó)內(nèi)郵寄快遞包裹,填單子的時(shí)候一般會(huì)寫“XX省XX市……”黎茎,前面不需要加上國(guó)家名稱囊颅。只有國(guó)際快遞,才需要寫上國(guó)名傅瞻。
但是如果我們希望獲得全部可以直接訪問(wèn)的鏈接踢代,怎么辦呢?
很容易俭正,也只需要一條 Python 語(yǔ)句。
r.html.absolute_links
這里焙畔,我們要的是“絕對(duì)”鏈接掸读,于是我們就會(huì)獲得下面的結(jié)果:
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-16-31-15-237773.png)
這回看著是不是就舒服多了?
我們的任務(wù)已經(jīng)完成了吧宏多?鏈接不是都在這里嗎儿惫?
鏈接確實(shí)都在這里了,可是跟我們的目標(biāo)是不是有區(qū)別呢伸但?
檢查一下肾请,確實(shí)有。
我們不光要找到鏈接更胖,還得找到鏈接對(duì)應(yīng)的描述文字呢铛铁,結(jié)果里包含嗎?
沒(méi)有却妨。
結(jié)果列表中的鏈接饵逐,都是我們需要的嗎?
不是彪标”度ǎ看長(zhǎng)度,我們就能感覺(jué)出許多鏈接并不是文中描述其他數(shù)據(jù)科學(xué)文章的網(wǎng)址捞烟。
這種簡(jiǎn)單粗暴直接羅列HTML文件中所有鏈接的方法薄声,對(duì)本任務(wù)行不通。
那么我們?cè)撛趺崔k题画?
我們得學(xué)會(huì)跟 Python 說(shuō)清楚我們要找的東西默辨。這是網(wǎng)頁(yè)抓取的關(guān)鍵。
想想看苍息,如果你想讓助手(人類)幫你做這事兒廓奕,怎么辦抱婉?
你會(huì)告訴他:
“尋找正文中全部可以點(diǎn)擊的藍(lán)色文字鏈接,拷貝文字到Excel表格桌粉,然后右鍵復(fù)制對(duì)應(yīng)的鏈接蒸绩,也拷貝到Excel表格。每個(gè)鏈接在Excel占一行铃肯,文字和鏈接各占一個(gè)單元格患亿。”
雖然這個(gè)操作執(zhí)行起來(lái)麻煩押逼,但是助手聽(tīng)懂后步藕,就能幫你執(zhí)行。
同樣的描述挑格,你試試說(shuō)給電腦聽(tīng)……不好意思咙冗,它不理解。
因?yàn)槟愫椭挚吹降木W(wǎng)頁(yè)漂彤,是這個(gè)樣子的雾消。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-16-42-24-952435.png)
電腦看到的網(wǎng)頁(yè),是這個(gè)樣子的挫望。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-16-43-10-688894.png)
為了讓你看得清楚源代碼立润,瀏覽器還特意對(duì)不同類型的數(shù)據(jù)用了顏色區(qū)分,對(duì)行做了編號(hào)媳板。
數(shù)據(jù)顯示給電腦時(shí)桑腮,上述輔助可視功能是沒(méi)有的。它只能看見(jiàn)一串串字符蛉幸。
那可怎么辦破讨?
仔細(xì)觀察,你會(huì)發(fā)現(xiàn)這些HTML源代碼里面奕纫,文字添忘、圖片鏈接內(nèi)容前后,都會(huì)有一些被尖括號(hào)括起來(lái)的部分若锁,這就叫做“標(biāo)記”搁骑。
所謂HTML,就是一種標(biāo)記語(yǔ)言(超文本標(biāo)記語(yǔ)言又固,HyperText Markup Language)仲器。
標(biāo)記的作用是什么?它可以把整個(gè)的文件分解出層次來(lái)仰冠。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-06-49-630506.png)
(圖片來(lái)源:https://goo.gl/kWCqS6)
如同你要發(fā)送包裹給某個(gè)人乏冀,可以按照“省-市-區(qū)-街道-小區(qū)-門牌”這樣的結(jié)構(gòu)來(lái)寫地址,快遞員也可以根據(jù)這個(gè)地址找到收件人洋只。
同樣辆沦,我們對(duì)網(wǎng)頁(yè)中某些特定內(nèi)容感興趣昼捍,可以依據(jù)這些標(biāo)記的結(jié)構(gòu),順藤摸瓜找出來(lái)肢扯。
這是不是意味著妒茬,你必須先學(xué)會(huì)HTML和CSS,才能進(jìn)行網(wǎng)頁(yè)內(nèi)容抓取呢蔚晨?
不是的乍钻,我們可以借助工具,幫你顯著簡(jiǎn)化任務(wù)復(fù)雜度铭腕。
這個(gè)工具银择,Google Chrome瀏覽器自帶。
我們?cè)跇永恼马?yè)面上累舷,點(diǎn)擊鼠標(biāo)右鍵浩考,在出現(xiàn)的菜單里面選擇“檢查”。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-11-50-177393.png)
這時(shí)被盈,屏幕下方就會(huì)出現(xiàn)一個(gè)分欄析孽。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-13-12-436452.png)
我們點(diǎn)擊這個(gè)分欄左上角(上圖紅色標(biāo)出)的按鈕。然后把鼠標(biāo)懸停在第一個(gè)文內(nèi)鏈接(《玉樹(shù)芝蘭》)上面害捕,點(diǎn)擊一下绿淋。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-14-22-049544.png)
此時(shí)闷畸,你會(huì)發(fā)現(xiàn)下方分欄里面尝盼,內(nèi)容也發(fā)生了變化。這個(gè)鏈接對(duì)應(yīng)的源代碼被放在分欄區(qū)域正中佑菩,高亮顯示盾沫。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-16-04-532914.png)
確認(rèn)該區(qū)域就是我們要找的鏈接和文字描述后,我們鼠標(biāo)右鍵選擇高亮區(qū)域殿漠,并且在彈出的菜單中赴精,選擇 Copy -> Copy selector。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-17-45-788878.png)
找一個(gè)文本編輯器绞幌,執(zhí)行粘貼蕾哟,就可以看見(jiàn)我們究竟復(fù)制下來(lái)了什么內(nèi)容。
body > div.note > div.post > div.article > div.show-content > div > p:nth-child(4) > a
這一長(zhǎng)串的標(biāo)記莲蜘,為電腦指出了:請(qǐng)你先找到 body 標(biāo)記谭确,進(jìn)入它管轄的這個(gè)區(qū)域后去找 div.note
標(biāo)記,然后找……最后找到 a 標(biāo)記票渠,這里就是要找的內(nèi)容了逐哈。
回到咱們的 Jupyter Notebook 中,用剛才獲得的標(biāo)記路徑问顷,定義變量sel昂秃。
sel = 'body > div.note > div.post > div.article > div.show-content > div > p:nth-child(4) > a'
我們讓 Python 從返回內(nèi)容中禀梳,查找 sel 對(duì)應(yīng)的位置,把結(jié)果存到 results 變量中肠骆。
results = r.html.find(sel)
我們看看 results 里面都有什么算途。
results
這是結(jié)果:
[<Element 'a' href='http://www.reibang.com/nb/130182' target='_blank'>]
results 是個(gè)列表,只包含一項(xiàng)哗戈。這一項(xiàng)包含一個(gè)網(wǎng)址郊艘,就是我們要找的第一個(gè)鏈接(《玉樹(shù)芝蘭》)對(duì)應(yīng)的網(wǎng)址。
可是文字描述“《玉樹(shù)芝蘭》”哪里去了唯咬?
別著急纱注,我們讓 Python 顯示 results 結(jié)果數(shù)據(jù)對(duì)應(yīng)的文本。
results[0].text
這是輸出結(jié)果:
'玉樹(shù)芝蘭'
我們把鏈接也提取出來(lái):
results[0].absolute_links
顯示的結(jié)果卻是一個(gè)集合胆胰。
{'http://www.reibang.com/nb/130182'}
我們不想要集合狞贱,只想要其中的鏈接字符串。所以我們先把它轉(zhuǎn)換成列表蜀涨,然后從中提取第一項(xiàng)瞎嬉,即網(wǎng)址鏈接。
list(results[0].absolute_links)[0]
這次厚柳,終于獲得我們想要的結(jié)果了:
'http://www.reibang.com/nb/130182'
有了處理這第一個(gè)鏈接的經(jīng)驗(yàn)氧枣,你信心大增,是吧别垮?
其他鏈接便监,也無(wú)非是找到標(biāo)記路徑,然后照貓畫虎嘛碳想。
可是烧董,如果每找一個(gè)鏈接,都需要手動(dòng)輸入上面這若干條語(yǔ)句胧奔,那也太麻煩了逊移。
這里就是編程的技巧了。重復(fù)逐條運(yùn)行的語(yǔ)句龙填,如果工作順利胳泉,我們就要嘗試把它們歸并起來(lái),做個(gè)簡(jiǎn)單的函數(shù)岩遗。
對(duì)這個(gè)函數(shù)扇商,只需給定一個(gè)選擇路徑(sel),它就把找到的所有描述文本和鏈接路徑都返回給我們喘先。
def get_text_link_from_sel(sel):
mylist = []
try:
results = r.html.find(sel)
for result in results:
mytext = result.text
mylink = list(result.absolute_links)[0]
mylist.append((mytext, mylink))
return mylist
except:
return None
我們測(cè)試一下這個(gè)函數(shù)钳吟。
還是用剛才的標(biāo)記路徑(sel)不變,試試看窘拯。
print(get_text_link_from_sel(sel))
輸出結(jié)果如下:
[('玉樹(shù)芝蘭', 'http://www.reibang.com/nb/130182')]
沒(méi)問(wèn)題红且,對(duì)吧坝茎?
好,我們?cè)囋嚳吹诙€(gè)鏈接暇番。
我們還是用剛才的方法嗤放,使用下面分欄左上角的按鈕點(diǎn)擊第二個(gè)鏈接。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-34-07-255683.png)
下方出現(xiàn)的高亮內(nèi)容就發(fā)生了變化:
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-33-33-680068.png)
我們還是用鼠標(biāo)右鍵點(diǎn)擊高亮部分壁酬,拷貝出 selector次酌。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-35-02-842966.png)
然后我們直接把獲得的標(biāo)記路徑寫到 Jupyter Notebook 里面。
sel = 'body > div.note > div.post > div.article > div.show-content > div > p:nth-child(6) > a'
用我們剛才編制的函數(shù)舆乔,看看輸出結(jié)果是什么岳服?
print(get_text_link_from_sel(sel))
輸出如下:
[('如何用Python做詞云?', 'http://www.reibang.com/p/e4b24a734ccc')]
檢驗(yàn)完畢希俩,函數(shù)沒(méi)有問(wèn)題吊宋。
下一步做什么?
你還打算去找第三個(gè)鏈接颜武,仿照剛才的方法做璃搜?
那你還不如全文手動(dòng)摘取信息算了,更省事兒一些鳞上。
我們要想辦法把這個(gè)過(guò)程自動(dòng)化这吻。
對(duì)比一下剛剛兩次我們找到的標(biāo)記路徑:
body > div.note > div.post > div.article > div.show-content > div > p:nth-child(4) > a
以及:
body > div.note > div.post > div.article > div.show-content > div > p:nth-child(6) > a
發(fā)現(xiàn)什么規(guī)律沒(méi)有?
對(duì)篙议,路徑上其他的標(biāo)記全都是一樣的唾糯,唯獨(dú)倒數(shù)第二個(gè)標(biāo)記("p")后冒號(hào)后內(nèi)容有區(qū)別。
這就是我們自動(dòng)化的關(guān)鍵了涡上。
上述兩個(gè)標(biāo)記路徑里面趾断,因?yàn)橹付嗽诘趲讉€(gè)“子”(nth-child
)文本段(paragraph,也就是"p"代表的含義)去找"a"這個(gè)標(biāo)記拒名,因此只返回來(lái)單一結(jié)果吩愧。
如果我們不限定"p"的具體位置信息呢?
我們?cè)囋嚳丛鱿裕@次保留標(biāo)記路徑里面其他全部信息雁佳,只修改"p"這一點(diǎn)。
sel = 'body > div.note > div.post > div.article > div.show-content > div > p > a'
再次運(yùn)行我們的函數(shù):
print(get_text_link_from_sel(sel))
這是輸出結(jié)果:
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-04-07-48-38-603409.png)
好了同云,我們要找的內(nèi)容糖权,全都在這兒了。
但是炸站,我們的工作還沒(méi)完星澳。
我們還得把采集到的信息輸出到Excel中保存起來(lái)。
還記得我們常用的數(shù)據(jù)框工具 Pandas 嗎旱易?又該讓它大顯神通了禁偎。
import pandas as pd
只需要這一行命令腿堤,我們就能把剛才的列表變成數(shù)據(jù)框:
df = pd.DataFrame(get_text_link_from_sel(sel))
讓我們看看數(shù)據(jù)框內(nèi)容:
df
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-54-03-439993.png)
內(nèi)容沒(méi)問(wèn)題,不過(guò)我們對(duì)表頭不大滿意如暖,得更換為更有意義的列名稱:
df.columns = ['text', 'link']
再看看數(shù)據(jù)框內(nèi)容:
df
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-55-02-015623.png)
好了笆檀,下面就可以把抓取的內(nèi)容輸出到Excel中了。
Pandas內(nèi)置的命令盒至,就可以把數(shù)據(jù)框變成csv格式酗洒,這種格式可以用Excel直接打開(kāi)查看。
df.to_csv('output.csv', encoding='gbk', index=False)
注意這里需要指定encoding(編碼)為gbk枷遂,否則默認(rèn)的utf-8編碼在Excel中查看的時(shí)候樱衷,有可能是亂碼。
我們看看最終生成的csv文件吧酒唉。
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-17-58-17-057507.png)
很有成就感箫老,是不是?
小結(jié)
本文為你展示了用Python自動(dòng)網(wǎng)頁(yè)抓取的基礎(chǔ)技能黔州。希望閱讀并動(dòng)手實(shí)踐后耍鬓,你能掌握以下知識(shí)點(diǎn):
- 網(wǎng)頁(yè)抓取與網(wǎng)絡(luò)爬蟲之間的聯(lián)系與區(qū)別;
- 如何用 pipenv 快速構(gòu)建指定的 Python 開(kāi)發(fā)環(huán)境流妻,自動(dòng)安裝好依賴軟件包牲蜀;
- 如何用 Google Chrome 的內(nèi)置檢查功能,快速定位感興趣內(nèi)容的標(biāo)記路徑绅这;
- 如何用 requests-html 包來(lái)解析網(wǎng)頁(yè)涣达,查詢獲得需要的內(nèi)容元素;
- 如何用 Pandas 數(shù)據(jù)框工具整理數(shù)據(jù)证薇,并且輸出到 Excel度苔。
或許,你覺(jué)得這篇文章過(guò)于淺白浑度,不能滿足你的要求寇窑。
文中只展示了如何從一個(gè)網(wǎng)頁(yè)抓取信息,可你要處理的網(wǎng)頁(yè)成千上萬(wàn)啊箩张。
別著急甩骏。
本質(zhì)上說(shuō),抓取一個(gè)網(wǎng)頁(yè)先慷,和抓取10000個(gè)網(wǎng)頁(yè)饮笛,在流程上是一樣的。
而且论熙,從咱們的例子里福青,你是不是已經(jīng)嘗試了抓取鏈接?
有了鏈接作為基礎(chǔ),你就可以滾雪球无午,讓Python爬蟲“爬”到解析出來(lái)的鏈接上二蓝,做進(jìn)一步的處理。
將來(lái)指厌,你可能還要應(yīng)對(duì)實(shí)踐場(chǎng)景中的一些棘手問(wèn)題:
- 如何把抓取的功能擴(kuò)展到某一范內(nèi)內(nèi)的所有網(wǎng)頁(yè)刊愚?
- 如何爬取Javascript動(dòng)態(tài)網(wǎng)頁(yè)?
- 假設(shè)你爬取的網(wǎng)站對(duì)每個(gè)IP的訪問(wèn)頻率做出限定踩验,怎么辦鸥诽?
- ……
這些問(wèn)題的解決辦法,我希望在今后的教程里面箕憾,一一和你分享牡借。
需要注意的是,網(wǎng)絡(luò)爬蟲抓取數(shù)據(jù)袭异,雖然功能強(qiáng)大钠龙,但學(xué)習(xí)與實(shí)踐起來(lái)有一定門檻。
當(dāng)你面臨數(shù)據(jù)獲取任務(wù)時(shí)御铃,應(yīng)該先檢查一下這個(gè)清單:
- 有沒(méi)有別人已經(jīng)整理好的數(shù)據(jù)集合可以直接下載碴里?
- 網(wǎng)站有沒(méi)有對(duì)你需要的數(shù)據(jù)提供API訪問(wèn)與獲取方式?
- 有沒(méi)有人針對(duì)你的需求上真,編好了定制爬蟲咬腋,供你直接調(diào)用?
如果答案是都沒(méi)有睡互,才需要你自己編寫腳本,調(diào)動(dòng)爬蟲來(lái)抓取就珠。
為了鞏固學(xué)習(xí)的知識(shí)寇壳,請(qǐng)你換一個(gè)其他網(wǎng)頁(yè),以咱們的代碼作為基礎(chǔ)修改后妻怎,抓取其中你感興趣的內(nèi)容壳炎。
如果能把你抓取的過(guò)程記錄下來(lái),在評(píng)論區(qū)將記錄鏈接分享給大家蹂季,就更好了冕广。
因?yàn)?strong>刻意練習(xí)是掌握實(shí)踐技能的最好方式疏日,而教是最好的學(xué)偿洁。
祝順利!
思考
本文主要內(nèi)容講解完畢沟优。
這里給你提一個(gè)疑問(wèn)涕滋,供你思考:
我們解析并且存儲(chǔ)的鏈接,其實(shí)是有重復(fù)的:
![](https://wphoto-1255363720.cosbj.myqcloud.com/2018-03-03-18-18-24-726975.png)
這并不是我們的代碼有誤挠阁,而是在《如何用《玉樹(shù)芝蘭》入門數(shù)據(jù)科學(xué)宾肺?》一文里溯饵,本來(lái)就多次引用過(guò)一些文章,所以重復(fù)的鏈接就都被抓取出來(lái)了锨用。
但是你存儲(chǔ)的時(shí)候丰刊,也許不希望保留重復(fù)鏈接。
這種情況下增拥,你該如何修改代碼啄巧,才能保證抓取和保存的鏈接沒(méi)有重復(fù)呢?
我把這一部分內(nèi)容掌栅,放到了文末的付費(fèi)閱讀區(qū)域秩仆。如果你愿意支持我的數(shù)據(jù)科學(xué)系列教程寫作,順便核對(duì)一下你的代碼是不是比我的更高效猾封,只需支付2塊錢(推廣期價(jià)格)澄耍,閱讀該部分內(nèi)容。
討論
你對(duì)Python爬蟲感興趣嗎晌缘?在哪些數(shù)據(jù)采集任務(wù)上使用過(guò)它齐莲?有沒(méi)有其他更高效的方式,來(lái)達(dá)成數(shù)據(jù)采集目的磷箕?歡迎留言铅搓,把你的經(jīng)驗(yàn)和思考分享給大家,我們一起交流討論搀捷。
如果你對(duì)我的文章感興趣星掰,歡迎點(diǎn)贊,并且微信關(guān)注和置頂我的公眾號(hào)“玉樹(shù)芝蘭”(nkwangshuyi)嫩舟。
如果本文可能對(duì)你身邊的親友有幫助氢烘,也歡迎你把本文通過(guò)微博或朋友圈分享給他們。讓他們一起參與到我們的討論中來(lái)家厌。