使用Node.js實現簡單的網路爬取

來源:互聯網
上載者:User

標籤:style   blog   http   io   color   ar   os   使用   java   

由於最近要實現一個爬取H5遊戲的Proxy 伺服器,隧看到這麼一篇不錯的文章(http://blog.miguelgrinberg.com/post/easy-web-scraping-with-nodejs),加之最近在學習Node.js,所以就準備翻譯出來加深一下印象。

轉載請註明來源:(www.cnblogs.com/xdxer )

 

在這篇文章中,我將會向大家展示如何用JavaScript配合Node.js寫一個網路爬取的指令碼。

網路抓取工具

在大部分情況下,一個網路抓取的指令碼只需要一種方法去下載整個頁面,然後搜尋裡面的資料。所有的現代語言都會提供方法去下載網頁,或者至少會有人實現了某個library或者一些其他的擴充包,所以這並不是一個痛點。然後,要精確定位並且找出在HTML中的資料是比較有難度的。一個HTML頁面混雜了許多內容、布局和樣式的變數,所以去解釋並且識別出那些我們關注的部分是一個挺不容易的工作。

舉個例子,考慮如下的HTML頁面:

<html>    <head>...</head>    <body>        <div id="content">            <div id="sidebar">            ...            </div>            <div id="main">                <div class="breadcrumbs">                ...                </div>                <table id="data">                    <tr><th>Name</th><th>Address</th></tr>                    <tr><td class="name">John</td><td class="address">Address of John</td></tr>                    <tr><td class="name">Susan</td><td class="address">Address of Susan</td></tr>                </table>            </div>        </div>    </body></html>

如果我們需要擷取到出現在 id = “data”這個表中的人名,那麼應該怎麼做呢?

一般的,網頁會被下載成一個字串的形式,然後只需要很簡單的對這個網頁進行檢索,檢索出那些出現在<td class = “name”> 之後,以</td>結尾的字串就可以了。

但是這種方式很容易會擷取到不正確的資料。網頁可能會有別的table,或者更加糟糕的是,原先的<td class="name"> 變成了 <td align="left" class="name"> ,這將會讓我們之前所制定的方案什麼都找不到。雖然說網頁的變化很容易導致一個爬取指令碼失效,但是假如我們可以清楚的知道元素是如何在HTML中組織的,那麼我們就不必總是重寫我們的爬取指令碼,當網頁改變的時候。

如果你寫過前端的js代碼,使用過jQuery,那麼你就會發現使用CSS selector 來選擇DOM中的元素是一件非常簡單的事情。舉個例子,在瀏覽器中,我們可以很簡單的爬取到那些名字使用如下的方式:

$(‘#data .name‘).each(function() {    alert($(this).text());});

 

介紹一下Node.js

http://nodejs.org (get it here!)

Javascript 是一個嵌入web瀏覽器的語言,感謝Node.js工程,我們現在可以編寫能夠獨立運行,並且甚至可以作為一個web server 的程式設計語言。

有很多現成的庫,例如jQuery那樣的。所以使用Javrscript+Node.js去實現這麼一個任務就非常便利了,因為我們可以使用那些現有的操作DOM元素的技術,這些技術在web瀏覽器上已經應用的比較成熟了。

Node.js有很多的庫,它是模組化的。本例子中需要用到兩個庫,request 和 cheerio。 request主要是用於下載那些網頁,cheerio 會在本地產生一棵DOM樹,然後提供一個jQuery子集去操作它們。安裝Node.js模組需要用到npm操作,類似於Ruby的gem 或者 Python的easy_install

有關於cheerio的一些API 可以參考這一篇CNode社區的文章 (https://cnodejs.org/topic/5203a71844e76d216a727d2e)

$ mkdir scraping$ cd scraping$ npm install request cheerio

如以上代碼所示,首先我們建立了一個目錄“scraping”,並且我們在在這個目錄下安裝了request 和 cheerio模組,事實上,nodejs的模組是可以進行全域性的安裝的,但是我更加喜歡locally的安裝,安裝的效果如所示。

那接下來我們就看看如何使用cheerio,來爬取上面的例子中的name,我們建立一個.js檔案 example.js,代碼如下:

var cheerio = require(‘cheerio‘);$ = cheerio.load(‘<html><head></head><body><div id="content">
<div id="sidebar"></div><div id="main">
<div id="breadcrumbs"></div><table id="data"><tr>
<th>Name</th><th>Address</th></tr><tr><td class="name">
John</td><td class="address">Address of John</td></tr>
<tr><td class="name">Susan</td><td class="address">
Address of Susan</td></tr></table></div></div></body></html>‘);$(‘#data .name‘).each(function() {    console.log($(this).text());});

輸出如下:

$ node example.jsJohnSusan
實際例子

http://www.thprd.org/schedules/schedule.cfm?cs_id=15 爬取這個網站中的議程表

代碼如下:

var request = require(‘request‘);var cheerio = require(‘cheerio‘);days = [‘Monday‘, ‘Tuesday‘, ‘Wednesday‘, ‘Thursday‘, ‘Friday‘, ‘Saturday‘, ‘Sunday‘];pools = {    ‘Aloha‘: 3,    ‘Beaverton‘: 15,    ‘Conestoga‘: 12,    ‘Harman‘: 11,    ‘Raleigh‘: 6,    ‘Somerset‘: 22,    ‘Sunset‘: 5,    ‘Tualatin Hills‘: 2};for (pool in pools) {    var url = ‘http://www.thprd.org/schedules/schedule.cfm?cs_id=‘ + pools[pool];    request(url, (function(pool) { return function(err, resp, body) {        $ = cheerio.load(body);        $(‘#calendar .days td‘).each(function(day) {            $(this).find(‘div‘).each(function() {                event = $(this).text().trim().replace(/\s\s+/g, ‘,‘).split(‘,‘);                if (event.length >= 2 && (event[1].match(/open swim/i) || event[1].match(/family swim/i)))                    console.log(pool + ‘,‘ + days[day] + ‘,‘ + event[0] + ‘,‘ + event[1]);            });        });    }})(pool));}
輸出如下:
$ node thprd.jsConestoga,Monday,4:15p-5:15p,Open Swim - M/LConestoga,Monday,7:45p-9:00p,Open Swim - M/LConestoga,Tuesday,7:30p-9:00p,Open Swim - M/LConestoga,Wednesday,4:15p-5:15p,Open Swim - M/LConestoga,Wednesday,7:45p-9:00p,Open Swim - M/LConestoga,Thursday,7:30p-9:00p,Open Swim - M/LConestoga,Friday,6:30p-8:30p,Open Swim - M/LConestoga,Saturday,1:00p-4:15p,Open Swim - M/LConestoga,Sunday,2:00p-4:15p,Open Swim - M/LAloha,Monday,1:05p-2:20p,Open SwimAloha,Monday,7:50p-8:25p,Open SwimAloha,Tuesday,1:05p-2:20p,Open SwimAloha,Tuesday,8:45p-9:30p,Open SwimAloha,Wednesday,1:05p-2:20p,Open SwimAloha,Wednesday,7:50p-8:25p,Open SwimAloha,Thursday,1:05p-2:20p,Open SwimAloha,Thursday,8:45p-9:30p,Open SwimAloha,Friday,1:05p-2:20p,Open SwimAloha,Friday,7:50p-8:25p,Open SwimAloha,Saturday,2:00p-3:30p,Open SwimAloha,Saturday,4:30p-6:00p,Open SwimAloha,Sunday,2:00p-3:30p,Open SwimAloha,Sunday,4:30p-6:00p,Open SwimHarman,Monday,4:25p-5:30p,Open Swim*Harman,Monday,7:30p-8:55p,Open SwimHarman,Tuesday,4:25p-5:10p,Open Swim*Harman,Wednesday,4:25p-5:30p,Open Swim*Harman,Wednesday,7:30p-8:55p,Open SwimHarman,Thursday,4:25p-5:10p,Open Swim*Harman,Friday,2:00p-4:55p,Open Swim*Harman,Saturday,1:30p-2:25p,Open SwimHarman,Sunday,2:00p-2:55p,Open SwimBeaverton,Tuesday,10:45a-12:55p,Open Swim (No Diving Well)Beaverton,Tuesday,8:35p-9:30p,Open Swim No Diving WellBeaverton,Thursday,10:45a-12:55p,Open Swim (No Diving Well)Beaverton,Thursday,8:35p-9:30p,Open Swim No Diving WellBeaverton,Saturday,2:30p-4:00p,Open SwimBeaverton,Sunday,4:15p-6:00p,Open SwimSunset,Tuesday,1:00p-2:30p,Open Swim/One Lap LaneSunset,Thursday,1:00p-2:30p,Open Swim/One Lap LaneSunset,Sunday,1:30p-3:00p,Open Swim/One Lap LaneTualatin Hills,Monday,7:35p-9:00p,Open Swim-Diving area opens at 8pmTualatin Hills,Wednesday,7:35p-9:00p,Open Swim-Diving area opens at 8pmTualatin Hills,Sunday,1:30p-3:30p,Open SwimTualatin Hills,Sunday,4:00p-6:00p,Open Swim
要注意的幾個問題: 非同步js的範圍問題,還有對網站結構的分析,我會在其他部落格中提到。
其實我只翻譯了很少的一部分,有興趣的可以去看一下原文,每一步都說的很仔細。

使用Node.js實現簡單的網路爬取

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.