各種語言寫網路爬蟲有什麼優點缺點?

現在好像很多人在用python
但也看到了PHP,JAVA,C++等等。
本人以上各種語言省慬皮毛。
該用那種語言開發爬蟲呢?


我來講一個特別的。當年在MSRA的時候寫爬蟲,就不需要訪問網路。我先以項目的原因跟Bing要資源,當然同時有它的集群和他的數據。爬蟲就是用Scope寫的,所謂的Scope長得很像SQL,然後在所有有表達式的地方都換成了C#代碼。所以基本都寫成map-reduce那樣子的,偶爾會使用group by啊order by啊join這些高級功能,狂甩正則表達式,特別方便。需要的中間數據結構全部做成臨時表/文件表,加上index,壓根不需要考慮內存和硬碟大小的問題。幾個超大的網站十幾個小時就趴下來了,還不用擔心被封。

這體驗比我以前用什麼雞巴語言用http爬都要爽。爬那麼多各種網站(主要是用來實現微軟的那個knowledge graph),寫的爬蟲用的時間,跟寫爬蟲爬一很太幾張破圖花的時間幾乎一樣長。

在做這個過做的過程中,體驗了一把整個公司的人都在為了「我要多用一點bing的資源」互相肛的過程,讓我得到了極大的成長。當然了,那種程序我再也不想寫了,太體力活了。要不是看在當年已經簽好了Offer要從MSRA走了沒事幹,這種事都是讓實習生來做的。


反對 @Kenneth ,他見過的爬蟲太少了

首先取決於目的

如果是一個站點,單一目的,用習慣的語言寫吧,學別的語言用的時間都夠重構兩遍的了。
如果是有100左右的站點,做個框架,把你的爬蟲管理起來,比起怎麼寫更重要。
ok,以上兩個都是 「手動」 寫模板的(當然,我們會有一些小插件等輔助工具)。手動寫模板的好處是:當站點不多的時候——快,靈活。在這樣的場景和目的下,選擇你習慣的語言,有最多頁面解析和 HTTP 請求支持的庫的語言最好。比如 python,java。
注意,這麼選擇的唯一原因是啟動成本高於編寫成本

當你面臨的是1000個站點這個量級的時候,可能你需要編寫一個模板生成器,比如 Kimono : Turn websites into structured APIs from your browser in seconds
當你面臨的是 1w 個站點以上,但是是同一類型的站點,可能你需要自動模板挖掘。
在這個階段,演算法更重要,所以代碼編寫的便利程度決定你的選擇。當然,當演算法穩定之後,就變成下面那個問題了。

當你面臨的是每天幾十億的網頁,來一次全量計算算一周,每個頁面需要提取標題,主圖,發布時間,網頁分塊,頁面價值。不可能有人給他們寫「腳本」,配模板。大量的建樹,分詞,機器學習,打分,follow 鏈接質量預測,篩選。佔用大量的計算。
這個階段,計算速度就非常重要了,除非你能說服老大,給你加幾千台機器。相對於這樣的需求,重新編寫所有基礎組件都可以。語言的選擇就會選擇執行速度快的了。

需要說明的一點是,靈活度,或者說抽取準確性,從上到下是依次遞減的。PM也不會要求你能對幾百億的網站準確抽取每個欄位對吧。


最後說一下抓取的問題。調度抓取對於每個爬蟲都是必要的,但卻沒什麼好說的,不同量級自然有不同的做法,但是這樣的系統一般目的明確,少包依賴,不需要你不斷修改。並且在架構中,往往可以是獨立組件,和下游是不同語言都行,愛用什麼寫用什麼寫。。
對於機房帶寬來說,下行基本是沒人用的,只要你和對方網站願意,抓取速度不是瓶頸。反而,計算對方壓力,篩選重複,高質鏈接更重要。而這又反過來帶來了計算的壓力。


用PHP做爬蟲相當簡單,稍微學習下simple_html_dom.php這個庫就可以分析DOM了.
比如抓取PHP官網首頁新聞插入資料庫並在Web上顯示只需幾行代碼:

&exec($ddl); } else { $db = new PDO("sqlite:".$file); }

require dirname(__FILE__)."/simple_html_dom.php";
$html = file_get_html("http://cn2.php.net");
$db-&>beginTransaction();
foreach($html-&>find("article.newsentry") as $v) {
$title = trim($v-&>find("h2.newstitle", 0)-&>plaintext);
$content = trim($v-&>find("div.newscontent", 0)-&>plaintext);
$time = trim($v-&>find("time", 0)-&>plaintext);
$stmt = $db-&>prepare("INSERT INTO test (title, content, time) VALUES (?, ?, ?)");
$stmt-&>execute(array($title, $content, $time));
$stmt = null;
}
$db-&>commit();

header("Content-Type: text/plain; charset=utf-8");
var_export($db-&>query("SELECT * FROM test")-&>fetchAll(PDO::FETCH_ASSOC));
$dbh = null;

另外PHP用libcurl庫提供的curl_multi也能並行發出多個HTTP請求:

https://my.oschina.net/eechen/blog/745224
介面1: php -S 127.0.0.1:8080 -t /home/eechen/www
介面2: php -S 127.0.0.2:8080 -t /home/eechen/www
/home/eechen/www/index.php:
& $_SERVER["SERVER_NAME"]));
//串列訪問需要sum(2,1)秒,並行訪問需要max(2,1)秒.
($_SERVER["SERVER_NAME"] == "127.0.0.1") ? sleep(2) : sleep(1);
?&>

並行發出多個請求:
& $v) {
$ch[$k] = curl_init($v);
curl_setopt($ch[$k], CURLOPT_HEADER, 0); //不輸出頭
curl_setopt($ch[$k], CURLOPT_RETURNTRANSFER, 1); //exec返回結果而不是輸出,用於賦值
curl_multi_add_handle($mh, $ch[$k]); //決定exec輸出順序
}
$running = null;
$starttime = microtime(true);
//執行批處理句柄(類似pthreads多線程里的start開始和join同步)
do {
//CURLOPT_RETURNTRANSFER如果為0,這裡會直接輸出獲取到的內容.
//如果為1,後面可以用curl_multi_getcontent獲取內容.
curl_multi_exec($mh, $running);
//阻塞直到cURL批處理連接中有活動連接,不加這個會導致CPU負載超過90%.
curl_multi_select($mh);
} while ($running &> 0);
echo microtime(true) - $starttime."
"; //耗時約2秒
foreach($ch as $v) {
$json[] = curl_multi_getcontent($v);
curl_multi_remove_handle($mh, $v);
}
curl_multi_close($mh);
var_export($json);
//輸出:
2.0015449523926
array (
0 =&> "{"SERVER_NAME":"127.0.0.1"}",
1 =&> "{"SERVER_NAME":"127.0.0.2"}",
)

當然,也可以使用PHP的多線程擴展pthreads用多線程實現並行發起多個請求,不過必須要求使用線程安全版本PHP.另外鳥哥的Yar擴展也支持並行調用,不過是用作PHP RPC的.

因為PHP內置了SQLite資料庫,所以存儲起來很方便.
又因為PHP內置了HTTP伺服器,所以展示起來也很方便.

建立HTTP服務:
php -S 127.0.0.1:8080 -t /www
打開瀏覽器訪問:
xdg-open http://127.0.0.1:8080


用Java寫過,語言笨重,所建立的數據模型的任何修改都會導致代碼大量變動,所以有些麻煩。
不過有個項目的一部分底層工具是爬網頁,再封裝一個業務層出來。業務厚重到這種程度,用Java就很舒服了。


沒人說下nodejs么?配合cheerio 簡單方便,一般簡單用用夠了。天生非同步,爬起來也很快。


update:2016-02-12

curl http://www.topit.me/|grep -P "http:[^&>]*?(jpg|gif)" -o|xargs wget

這就是一個正則搜索url中以http開頭 jpg或gif結尾的字元串,使用wget下載的例子

2015-02-22 原答案:
寫過一個爬圖片的程序,使用的shell,加到crontab裡面
大概是curl | grep | wget 一句話
是不是更簡單?


謝邀!
我用 PHP 和 Python 都寫過爬蟲和正文提取程序。
最開始使用 PHP 所以先說說 PHP 的優點:
1.語言比較簡單,PHP 是非常隨意的一種語言。寫起來容易讓你把精力放在你要做的事情上,而不是各種語法規則等等。
2.各種功能模塊齊全,這裡分兩部分:
1.網頁下載:curl 等擴展庫;
2.文檔解析:dom、xpath、tidy、各種轉碼工具,可能跟題主的問題不太一樣,我的爬蟲需要提取正文,所以需要很複雜的文本處理,所以各種方便的文本處理工具是我的大愛。;
總之容易上手。

缺點:
1.並發處理能力較弱:由於當時 PHP 沒有線程、進程功能,要想實現並發需要借用多路服用模型,PHP 使用的是 select 模型。實現其來比較麻煩,可能是因為水平問題我的程序經常出現一些錯誤,導致漏抓。

再說說 Python:
優點:
1.各種爬蟲框架,方便高效的下載網頁;
2.多線程、進程模型成熟穩定,爬蟲是一個典型的多任務處理場景,請求頁面時會有較長的延遲,總體來說更多的是等待。多線程或進程會更優化程序效率,提升整個系統下載和分析能力。
3.GAE 的支持,當初寫爬蟲的時候剛剛有 GAE,而且只支持 Python ,利用 GAE 創建的爬蟲幾乎免費,最多的時候我有近千個應用實例在工作。

缺點:
1.對不規範 HTML 適應能力差:舉個例子,如果一個頁面裡面同時有 GB18030 字符集的中文和 UTF-8 字符集的中文,Python 處理起來就沒有 PHP 那麼簡單,你自己需要做很多的判斷工作。當然這是提取正文時的麻煩。

Java 和 C++ 當時也考察過,相對腳本語言比較麻煩,所以放棄。

總之,如果開發一個小規模的爬蟲腳本語言是個各方面比較有優勢的語言。如果要開發一個複雜的爬蟲系統可能 Java 是個增加選項, C++ 我感覺寫個模塊之類的更加適合。對於一個爬蟲系統來說,下載和內文解析只是基本的兩個功能。真正好的系統還包括完善的任務調度、監控、存儲、頁面數據保存和更新邏輯、排重等等。爬蟲是一個耗費帶寬的應用,好的設計會節約大量的帶寬和伺服器資源,並且好壞差距很大。


和語言沒啥關係,主要是有沒有相應庫的支持。


Lua 或許也是一個不錯的選擇。

語言簡單;協程支持,使用同步API編寫爬蟲,方便。執行效率也高。

IronsDu/Joynet 是一個(根據關鍵字搜索相關話題下)爬知乎圖片的爬蟲程序。


爬蟲這種應用,看的不是單機的代碼執行速度,看的是開發效率和工具便捷性。所以語言越簡單越好。


爬蟲可以認為是每個學計算機的用來滿足個人興趣最好的入門項目之一了。
就基本功能而言,理論上每種語言都可以用來寫爬蟲,本質就是一個大循環和字元串提取嘛。我在讀研時有一位師兄自己用C++鼓搗出一個爬項目有關數據的小爬蟲,我心想畫風不太對啊?不應該是Python或者是Java么?
確實,現在大多數的爬蟲都是基於Python的,github上一大堆。最出名的框架就是Scrapy。Java也有Jsoup,Jaunt等工具。高級語言之所以稱之為高級語言,在於很多事情通過自身設計或者是第三方庫它給你做好了,你直接用行了。
從我寫爬蟲的經驗來看,爬蟲的難點主要在以下幾個地方:
1. 不規則網頁的處理。一個隨心所欲添加內容的站點是爬蟲最頭痛的,那種簡單的幾個for搞不定的頁面結構總是會給你的log帶來一堆Error。這種,說實話不太建議用框架,有這研究框架和添加例外處理的時間,自己選最熟的語言手寫早就寫完了。一味相信成熟的框架會有種殺雞用牛刀的感覺,這個雞還總是飛。
2. 網站反爬蟲。爬蟲最喜歡那種一點都不抵抗的網站。然而如果網站管理員對數據安全有意識,肯定會加一堆反爬蟲策略,無非就是那麼幾種,這種就是框架的好處了。Scrapy處理這些很happy。
3. 動態載入的網站。爬蟲最喜歡那種躺著不動的網站。動態網站需要你在爬蟲里先執行網站的js腳本再獲取內容。這裡PhantomJS/casperJs和Selenium都能很好地解決。現在一些成熟的框架也都支持這些。
4. 大規模。這個其實只要你有足夠的內存和計算能力,都不是大問題,框架都給你了。

如果沒有這些問題的考慮,還是拿最熟的語言手寫先試試吧。
如果什麼語言都不熟也不想深入,那就先去github下一個你目標網站的爬蟲repo,稍微改改代碼基本就能用了。


用c++、python、erlang、scala、go、js都寫過爬蟲


簡單說,技術方案,首先得看需求:

1. 抓什麼:是純HTML頁面,還是說需要動態渲染;還是說抓APP內的數據;這些都會影響到方案的選擇

2. 數據規模:如果就抓來玩玩,每天幾千幾萬的規模,任何語言都足夠了

3. 是否需要做處理:這個展開細節就多了,不過我們理解的爬蟲一般就負責抓,處理就給ETL階段來就可以了

4. 是否涉及到複雜的交互,例如登陸,驗證碼一系列的操作等等

如果就純粹寫著玩,用python挺好的,框架可以直接用scrapy,一兩個小時即可完整一個比較完整的爬蟲;如果有渲染需求,可以直接調用selenium,非常方便


如果要涉及到高並發,例如一台機器有幾千個並發,那麼用erlang/scala/go這些原生支持高並發的語言會更合適;不過鑒於erlang本身在字元串處理方面比較弱,所以更推薦scala go,單機支撐幾千並發沒啥壓力


如果涉及到大量頁面渲染,那麼就很麻煩了,一般拿基於webkit之類的,例如phantomjs,改造一下來弄弄也可以滿足需求;如果需要大規模抓取的話,那麼可以把視覺渲染部分邏輯去掉,僅僅保留js渲染(很長時間沒研究爬蟲了,現在應該有直接做js渲染的引擎了)


上述東西,其實不算複雜,但是一個完整的爬蟲,會涉及到很多技術點,例如:

1. 認證,驗證碼,各種加密

2. IP的問題,這個解決方案也很多

3. 數據的處理

4. 分散式(如果有幾百上千個節點,這個任務調度就非常重要了)


這個要看你的具體業務吧。以前為了一個爬蟲任務,被爬的對象全是動態渲染的(某博就是這樣喪心病狂),於是就要找一個無界面瀏覽器,經過選擇PhantomJS最合適,所以就採用了JavaScript。


爬蟲的本質就是抓取網頁,分析內容,把你想要的部分提取出來,模式是固定的,任何語言都是這麼搞的。由於模式固定,遇到的問題類似,容易一般化,故出現了大量的爬蟲框架

所以你需要關注的是你擅長哪種語言,該語言哪個爬蟲框架最好用

語言辣么多,框架辣么多,分析到啥時候是個頭兒!


Scala也挺好的,因為有akka。


就像 @kenneth 所說的。開發效率很重要。因為爬蟲的具體代碼得根據網站不同而修改的,而Python這種靈活的腳本語言特別適合這種任務。
同時Python還有強大的爬蟲庫比如Scrapy。


我用golang做過,高並發能力強


寫爬蟲這種交給實習生寫就行了。。。


Java,PHP,Nodejs,Python,Golang這幾種常見語言都可以寫。C++/C也可以寫,不過渣渣很少人寫。


爬蟲一般爬http或加密https,一條鏈接,post或get,保存cookie或者偽裝一些頭部。

任何語言都有http庫,自己封一下就行。

優缺點可以把題目換成

各種計算機語言有什麼優缺點?

本人只寫過Python和Golang的爬蟲,分散式爬蟲Go寫起來舒服一點,僅僅就是不用縮進,還可以一言不合就go!


學習了,都是大牛啊


推薦一個C#寫的爬蟲軟體,這個軟體已經有十來年,架構較為成熟,速度快,使用簡單。http://www.sensite.cn/bget,除了添加抓取任務,還可以在上面開發自己的插件。


推薦閱讀:

大文件傳輸主要技術瓶頸都有哪些?如何處理的?
HTTPS除了使用CA機構頒發的數字證書外,有沒有使用數字簽名技術驗證內容的完整性?
如何去分析開源的代碼,例如tomcat?
RPC框架和簡單的request - reponse的web框架有什麼區別?
JVM 常量池中存儲的是對象還是引用呢?

TAG:Python | PHP | Java | 爬蟲計算機網路 | C |