可以在GitHub上找到本教程的源代碼。為了運行示例,您需要同時安裝node.js和phantomjs。可以在此處找到用於下載和安裝的說明:node.js,phantomjs。
>設置基本命令行框架任何CLI框架的核心是將命令轉換為一個或多個可選或必需的參數,轉換為具體操作的概念。在這方面非常有用的兩個NPM軟件包是指揮官和提示。
指揮官允許您定義支持哪些參數,同時提示允許您(足夠適當地)提示用戶在運行時輸入。最終結果是一個句法甜蜜的界面,用於基於某些用戶提供的數據,以動態行為執行各種動作。
>說,例如,我們希望我們的命令看起來像這樣:
>$ <span>node run.js -x hello_world </span>
我們的入口點(run.js)定義了這樣的參數:
>program <span>.version('1.0.0') </span> <span>.option('-x --action-to-perform [string]', 'The type of action to perform.') </span> <span>.option('-u --url [string]', 'Optional URL used by certain actions') </span> <span>.parse(process.argv); </span>
並定義了這樣的各種用戶輸入案例:
><span>var performAction = require('./actions/' + program.actionToPerform) </span> <span>switch (program.actionToPerform) { </span> <span>case 'hello_world': </span> prompt<span>.get([{ </span> <span>// What the property name should be in the result object </span> <span>name: 'url', </span> <span>// The prompt message shown to the user </span> <span>description: 'Enter a URL', </span> <span>// Whether or not the user is required to enter a value </span> <span>required: true, </span> <span>// Validates the user input </span> <span>conform: function (value) { </span> <span>// In this case, the user must enter a valid URL </span> <span>return validUrl.isWebUri(value); </span> <span>} </span> <span>}], function (err<span>, result</span>) { </span> <span>// Perform some action following successful input </span> <span>performAction(phantomInstance, result.url); </span> <span>}); </span> <span>break; </span><span>} </span>在這一點上,我們已經定義了一個基本路徑,可以通過該路徑指定執行操作,並添加了一個提示以接受URL。我們只需要添加一個模塊來處理該操作的邏輯即可。我們可以通過將一個名為hello_world.js的文件添加到操作目錄中來做到這一點:
>
如您所見,該模塊期望提供一個phantomjs對象(Phantominstance)和URL(URL)的實例。我們將暫時地定義Phantomjs實例的細節,但是目前足以看到我們為觸發特定動作奠定了基礎。既然我們已經制定了一定的慣例,我們可以輕鬆地以定義和理智的方式添加新的動作。<span>'use strict'; </span> <span>/** </span><span> * <span>@param Horseman phantomInstance </span></span><span> * <span>@param string url </span></span><span> */ </span>module<span>.exports = function (phantomInstance<span>, url</span>) { </span> <span>if (!url || typeof url !== 'string') { </span> <span>throw 'You must specify a url to ping'; </span> <span>} else { </span> <span>console.log('Pinging url: ', url); </span> <span>} </span> phantomInstance <span>.open(url) </span> <span>.status() </span> <span>.then(function (statusCode) { </span> <span>if (Number(statusCode) >= 400) { </span> <span>throw 'Page failed with status: ' + statusCode; </span> <span>} else { </span> <span>console.log('Hello world. Status code returned: ', statusCode); </span> <span>} </span> <span>}) </span> <span>.catch(function (err) { </span> <span>console.log('Error: ', err); </span> <span>}) </span> <span>// Always close the Horseman instance </span> <span>// Otherwise you might end up with orphaned phantom processes </span> <span>.close(); </span><span>}; </span>> 使用騎兵
爬行
>
現在,當我們運行命令時,騎手實例和輸入URL將傳遞到Hello_world模塊,導致Phantomjs請求URL,捕獲其狀態代碼並將狀態打印到控制台。我們剛剛使用騎馬者進行了第一個真正的善意爬行。 giddyup!
<span>var phantomInstance = new Horseman({ </span> <span>phantomPath: '/usr/local/bin/phantomjs', </span> <span>loadImages: true, </span> <span>injectJquery: true, </span> <span>webSecurity: true, </span> <span>ignoreSSLErrors: true </span><span>}); </span> <span>performAction(phantomInstance, ...); </span>
複合互動的騎士方法
到目前為止,我們已經研究了非常簡單的騎士用法,但是當我們將其方法鏈接在一起以在瀏覽器中執行一系列操作時,包裝可以做得更多。為了演示其中一些功能,讓我們定義一個動作,該操作模擬了通過GitHub導航以創建新存儲庫的用戶。
請注意:此示例純粹是出於演示目的,不應被視為創建GitHub存儲庫的可行方法。這僅僅是一個人如何使用騎手與Web應用程序進行交互的示例。如果您有興趣以自動方式創建存儲庫,則應使用官方的GitHub API。
讓我們假設新的爬網會像這樣觸發:>按照我們已經制定的CLI框架的約定,我們需要在名為create_repo.js的操作目錄中添加一個新模塊。與我們以前的“ Hello World”示例一樣,create_repo模塊導出一個包含該動作的所有邏輯的單個函數。
$ <span>node run.js -x hello_world </span>
請注意,在此操作中,我們將更多的參數傳遞給導出的函數,而不是以前。這些參數包括用戶名,密碼和存儲庫。一旦用戶成功完成了及時挑戰,我們將從run.js傳遞這些值。
program <span>.version('1.0.0') </span> <span>.option('-x --action-to-perform [string]', 'The type of action to perform.') </span> <span>.option('-u --url [string]', 'Optional URL used by certain actions') </span> <span>.parse(process.argv); </span>>在發生任何事情之前,我們必須添加邏輯。我們通過將案例添加到我們的主開關語句中來做到這一點:
>現在我們將此掛鉤添加到run.js,當用戶輸入相關數據時,它將傳遞給操作,從而使我們可以繼續進行爬網。
至於Create_repo爬網邏輯本身,我們使用騎手的方法來導航到GitHub登錄頁面,輸入提供的用戶名和密碼,然後提交表單:<span>var performAction = require('./actions/' + program.actionToPerform) </span> <span>switch (program.actionToPerform) { </span> <span>case 'hello_world': </span> prompt<span>.get([{ </span> <span>// What the property name should be in the result object </span> <span>name: 'url', </span> <span>// The prompt message shown to the user </span> <span>description: 'Enter a URL', </span> <span>// Whether or not the user is required to enter a value </span> <span>required: true, </span> <span>// Validates the user input </span> <span>conform: function (value) { </span> <span>// In this case, the user must enter a valid URL </span> <span>return validUrl.isWebUri(value); </span> <span>} </span> <span>}], function (err<span>, result</span>) { </span> <span>// Perform some action following successful input </span> <span>performAction(phantomInstance, result.url); </span> <span>}); </span> <span>break; </span><span>} </span>
我們通過等待表單提交頁面加載來繼續鏈條:
之後,我們使用jQuery來確定登錄是否成功:
<span>'use strict'; </span> <span>/** </span><span> * <span>@param Horseman phantomInstance </span></span><span> * <span>@param string url </span></span><span> */ </span>module<span>.exports = function (phantomInstance<span>, url</span>) { </span> <span>if (!url || typeof url !== 'string') { </span> <span>throw 'You must specify a url to ping'; </span> <span>} else { </span> <span>console.log('Pinging url: ', url); </span> <span>} </span> phantomInstance <span>.open(url) </span> <span>.status() </span> <span>.then(function (statusCode) { </span> <span>if (Number(statusCode) >= 400) { </span> <span>throw 'Page failed with status: ' + statusCode; </span> <span>} else { </span> <span>console.log('Hello world. Status code returned: ', statusCode); </span> <span>} </span> <span>}) </span> <span>.catch(function (err) { </span> <span>console.log('Error: ', err); </span> <span>}) </span> <span>// Always close the Horseman instance </span> <span>// Otherwise you might end up with orphaned phantom processes </span> <span>.close(); </span><span>}; </span>
>在我們的個人資料頁面上,我們將導航到我們的存儲庫標籤:
<span>var phantomInstance = new Horseman({ </span> <span>phantomPath: '/usr/local/bin/phantomjs', </span> <span>loadImages: true, </span> <span>injectJquery: true, </span> <span>webSecurity: true, </span> <span>ignoreSSLErrors: true </span><span>}); </span> <span>performAction(phantomInstance, ...); </span>
在我們的存儲庫選項卡時,我們檢查是否已經存在帶有指定名稱的存儲庫。如果是這樣,那麼我們會丟下錯誤。如果不是,那麼我們繼續我們的順序:
$ <span>node run.js -x create_repo </span>
假設沒有錯誤,我們通過編程單擊“新存儲庫”按鈕並等待下一頁:
module<span>.exports = function (phantomInstance<span>, username, password, repository</span>) { </span> <span>if (!username || !password || !repository) { </span> <span>throw 'You must specify login credentials and a repository name'; </span> <span>} </span> <span>... </span><span>} </span>
之後,我們輸入提供的存儲庫名稱並提交表格:
<span>switch (program.actionToPerform) { </span> <span>case 'create_repo': </span> prompt<span>.get([{ </span> <span>name: 'repository', </span> <span>description: 'Enter repository name', </span> <span>required: true </span> <span>}, { </span> <span>name: 'username', </span> <span>description: 'Enter GitHub username', </span> <span>required: true </span> <span>}, { </span> <span>name: 'password', </span> <span>description: 'Enter GitHub password', </span> <span>hidden: true, </span> <span>required: true </span> <span>}], function (err<span>, result</span>) { </span> <span>performAction( </span> phantomInstance<span>, </span> result<span>.username, </span> result<span>.password, </span> result<span>.repository </span> <span>); </span> <span>}); </span> <span>break; </span> <span>... </span>>一旦到達生成頁面,我們就會知道存儲庫是創建的:
與任何騎馬爬行一樣,至關重要的是,我們結束了騎馬的實例:
phantomInstance <span>.open('https://github.com/login') </span> <span>.type('input[name="login"]', username) </span> <span>.type('input[name="password"]', password) </span> <span>.click('input[name="commit"]') </span>
>未能關閉騎士實例可能會導致機器上的孤立phantomjs處理。
<span>.waitForNextPage() </span>>爬行以收集數據
在這一點上,我們已經組裝了一系列靜態序列,以編程方式在GitHub上創建一個新的存儲庫。為此,我們鏈接了一系列的騎手方法。
這種方法對於事先已知的特定結構和行為模式可能很有用,但是,您可能會發現您需要在某個時候實現更靈活的腳本。如果您的動作序列有可能根據上下文變化或產生多個不同的結果,則可能是這種情況。如果您需要從DOM中提取數據,也將是這種情況。
在這種情況下,您可以使用Horseman的evaliate()方法,它允許您通過注入內聯或外部鏈接JavaScript來執行瀏覽器中的自由形式交互。>
>本節演示了從頁面中提取基本數據的示例(在這種情況下,錨點鏈接)。可能需要這種情況的一種情況是構建一個污損檢測軌,以擊中域上的每個URL。與我們的最後一個示例一樣,我們必須首先在操作目錄中添加一個新模塊:
,然後在run.js中為新操作添加一個鉤子:
$ <span>node run.js -x hello_world </span>>
現在,此代碼已經到位,我們可以通過運行以下命令來從任何給定的頁面提取鏈接:
program <span>.version('1.0.0') </span> <span>.option('-x --action-to-perform [string]', 'The type of action to perform.') </span> <span>.option('-u --url [string]', 'Optional URL used by certain actions') </span> <span>.parse(process.argv); </span>
>此操作演示了從頁面上提取數據,並且不會利用騎手內置的任何瀏覽器操作。它直接執行您在estuation()方法中放置的任何JavaScript,並且會像在瀏覽器環境中本地運行一樣。
><span>var performAction = require('./actions/' + program.actionToPerform) </span> <span>switch (program.actionToPerform) { </span> <span>case 'hello_world': </span> prompt<span>.get([{ </span> <span>// What the property name should be in the result object </span> <span>name: 'url', </span> <span>// The prompt message shown to the user </span> <span>description: 'Enter a URL', </span> <span>// Whether or not the user is required to enter a value </span> <span>required: true, </span> <span>// Validates the user input </span> <span>conform: function (value) { </span> <span>// In this case, the user must enter a valid URL </span> <span>return validUrl.isWebUri(value); </span> <span>} </span> <span>}], function (err<span>, result</span>) { </span> <span>// Perform some action following successful input </span> <span>performAction(phantomInstance, result.url); </span> <span>}); </span> <span>break; </span><span>} </span>>在本節中應注意的最後一件事,該部分提到了較早的提及:不僅可以使用estaution()方法在瀏覽器中執行自定義JavaScript,而且還可以在運行之前將外部腳本注入運行時環境您的評估邏輯。可以這樣做:
>通過擴展上面的邏輯,您幾乎可以在任何網站上執行任何操作。
><span>'use strict'; </span> <span>/** </span><span> * <span>@param Horseman phantomInstance </span></span><span> * <span>@param string url </span></span><span> */ </span>module<span>.exports = function (phantomInstance<span>, url</span>) { </span> <span>if (!url || typeof url !== 'string') { </span> <span>throw 'You must specify a url to ping'; </span> <span>} else { </span> <span>console.log('Pinging url: ', url); </span> <span>} </span> phantomInstance <span>.open(url) </span> <span>.status() </span> <span>.then(function (statusCode) { </span> <span>if (Number(statusCode) >= 400) { </span> <span>throw 'Page failed with status: ' + statusCode; </span> <span>} else { </span> <span>console.log('Hello world. Status code returned: ', statusCode); </span> <span>} </span> <span>}) </span> <span>.catch(function (err) { </span> <span>console.log('Error: ', err); </span> <span>}) </span> <span>// Always close the Horseman instance </span> <span>// Otherwise you might end up with orphaned phantom processes </span> <span>.close(); </span><span>}; </span>使用騎手屏幕截圖
>我想證明的最終用例是您將如何使用Horseman拍攝屏幕截圖。我們可以使用Horseman的ScreenShotBase64()方法來完成此操作,該方法返回代表屏幕截圖的base64編碼字符串。
,然後在run.js中為新操作添加一個鉤子:
>
<span>var phantomInstance = new Horseman({ </span> <span>phantomPath: '/usr/local/bin/phantomjs', </span> <span>loadImages: true, </span> <span>injectJquery: true, </span> <span>webSecurity: true, </span> <span>ignoreSSLErrors: true </span><span>}); </span> <span>performAction(phantomInstance, ...); </span>現在,您可以使用以下命令進行屏幕截圖:
>
$ <span>node run.js -x create_repo </span>>使用base64編碼字符串的原因(例如,保存實際圖像)是它們是表示原始圖像數據的便捷方法。這個堆疊式的答案更詳細。
>
如果要保存實際映像,則使用屏幕截圖()方法。module<span>.exports = function (phantomInstance<span>, username, password, repository</span>) { </span> <span>if (!username || !password || !repository) { </span> <span>throw 'You must specify login credentials and a repository name'; </span> <span>} </span> <span>... </span><span>} </span>>
本教程試圖展示自定義的CLI微框架和一些基本的邏輯,用於使用Horseman軟件包來利用Phantomjs,以爬Node.js爬網。雖然使用CLI框架可能會使許多項目受益,但爬行通常僅限於非常特定的問題域。一個共同的領域是質量保證(QA),可以將爬網用於功能和用戶界面測試。另一個領域是安全性,例如,您可能想定期爬網,以檢測到它是否已被污損或折衷。
>無論您的項目可能是什麼情況,請確保清楚地定義您的目標並儘可能不引人注目。在可能的情況下獲得許可,請在最大程度上禮貌,並註意永遠不要DDOS。如果您懷疑自己正在產生大量的自動流量,那麼您可能會重新評估您的目標,實施或許可水平。
經常詢問的問題(常見問題解答)有關網絡爬行的節點和phantomjs騎手 Web爬網和Web刮擦是兩個不同的過程,儘管它們通常可以互換使用。網絡爬行是系統瀏覽網絡的過程,通常由機器人或蜘蛛進行。它涉及索引網站的內容和以下鏈接到其他網頁。另一方面,網絡刮擦是從網站提取特定數據的過程。它涉及解析網頁的HTML以刪除所需的數據。雖然網絡爬網是關於導航和索引的,但網絡刮擦是關於數據提取的。
異步性質。它允許並發處理,這意味著您可以同時爬網多頁。這使其比同步執行的其他語言要快得多。此外,Node.js擁有一個豐富的生態系統,具有許多可以幫助網絡爬行的庫和工具,例如Phantomjs Horseman。 > Phantomjs Horseman是一個Node.js軟件包,可為使用Phantomjs自動化Web瀏覽器提供高級API。它允許您在網頁上執行操作,例如單擊鏈接,填寫表單和屏幕截圖。這使其成為網絡爬網的強大工具,因為它使您可以像人類用戶一樣與網頁進行交互。
>我可以使用Web爬網來監視網站上的更改嗎? ,網絡爬行可用於監視網站上的更改。通過定期爬行網站並將當前狀態與以前的狀態進行比較,您可以檢測任何更改。這對於各種目的可能很有用,例如在電子商務網站上跟踪價格變化或監視新聞網站上的更新。
以上是網絡與節點,phantomjs和騎手一起爬行的詳細內容。更多資訊請關注PHP中文網其他相關文章!