網路機器人、網路蜘蛛與網路爬蟲 PHP/CURL程式設計指南(第二版)
Michael Schrenk 著 / 藍子軒 譯
Part I 基本概念與技術
Chapter 1. 網路機器人是什麼?能吃嗎?
- 解放網際網路真正的淺力
- 對程式開發者的用處:
有趣、讓駭客行為變得有建設性 - 對企業領導者的用處:
客製化應用、小投資大收穫
Chapter 2. 關於網路機器人的一些構想
- 從瀏覽器的限制中獲取靈感:
- TrackRates.com : 彙整篩選飯店房價
- WebSiteOptimization.com : 分析網站效能
- Pokerbot : 撲克牌機器人,模仿行為
Chapter 3. 下載網頁
- 把它想成是檔案,而不是網頁
- 利用PHP的內建函式來下載檔案
1. 使用fopen() + fgets()
<?php
$target = "http://www.webbotsspidersscreenscrapers.com/hello_world.html";
$file_handle = fopen($target, "r");
while(!feof($file_handle))
echo fgets($file_handle, 4096);
fclose($file_handle);
?>
2. 使用file()
<?php
$target = "http://www.webbotsspidersscreenscrapers.com/hello_world.html";
$downloaded_page_array = file($target);
for($xx=0; $xx<cout($downloaded_page_array); $xx++)
echo $downloaded_page_array[$xx]
?>
- PHP/CURL簡介
名稱由來:client+URL
- 支援多種傳輸協定
- 表單提交
- 基本身份認證
- Cookie
- 重導向
- 假冒代理程式的名稱
- 引用參照的管理
- Socket管理
- 安裝PHP/CURL
- LIB_http
Chapter 4. 基本解析技術
- 資料就藏在一堆標籤中
- 如果HTML寫得很爛,該如何解析?
>使用HTMLTidy函式庫進行預處理 - 標準解析常函式
- 使用LIB_parse
- 幾個有用的PHP函式
- stristr() : 測試字串是否包含在字串,在乾草堆(haystack,未解析的文字)中找縫衣針(needle,子字串),strstr()分大小寫
- str_replace() : 字串取代
- strip_tags() : 去除HTML格式
- similar_test() : 比較相似程度
- 最終的想法
- 千萬不要信任一個原始碼寫得很差的網頁
- 解析時盡量區分成幾個小步驟
- 就算是除錯,也別用瀏覽器來展現解析結果
- 使用正規表示法時要特別謹慎
Chapter 5. 運用正規表達式的高級解析技術
- 正規表示法的關鍵-模式匹配
- PHP的正規表示法有兩種:
- PCRE(Perl相容正規表示法,以preg_開頭)
- POSIX(延伸正規表示法,以ereg開頭,PHP 5.3.0以後棄用)
PHP正規表示法函式:
preg_replace(pattern, replacement, subject)
preg_match(pattern, subject)
preg_match_all(pattern, subject, result_array)
preg_split(pattern, subject)
透過範例學習模式
\d: 數字
\d+: 1個以上的數字
\b: 邊界
\D: 非數字字元
\b\D\D\D\b or \b\D{3}\b: 匹配連續3個字母
.: wildcard正規表示法中,對網路機器人開發者特別有趣的部分
哪些情況適合(或不適合)使用正規表示法作為解析工具?
正規表示法的缺點:不擅長表達資料間的關聯性、正規表示法提供太多選擇、正規表示法比較難以除錯、正規表示法會讓你的程式碼變複雜
Chapter 6. 表單提交的自動化
對表單介面進行逆向工程
表單處理器、資料欄位、傳遞方法、事件觸發
1
2
3
4<form name="frml" action="form_handler"(表單處理器) method="get"(傳遞方法)>
<input type="textbox" name="email">(資料欄位)
<input type="submit">(事件觸發)
</form>表單處理器(Form Handler)
action屬性,不指定的話則與處理表單為同一個頁面。
資料欄位(Data Field)
最重要的是名稱(name)與值(value)。
傳遞方法(Method)
GET:250字元長度左右、資料無法加密
POST:好幾MB、資料可以加密
Multipart Encoding:POST方法的延伸,可以傳送local檔案1
2
3
4
5
6
7
8
9
10<form name="frm1" method="POST" enctype="multipart/form-data" action="...">
</form>
//script版本:
$post = array("uploadedfile" => "@".$full_path_name_of_file);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $form_action_URL);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$response = curl_exec($ch);事件觸發(Event Trigger)
無法預測的表單
- JavaScript:有可能改變表單
- 機器生成HTML的可讀性
- Cookie的存在
- 表單的分析
如果包含session id就需要先下載網頁進行解析
Chapter 7. 管理大量的資料
- 資料的組織化
根據資料特性選擇儲存結構
命名慣例
- 切實執行
- 使用物件的類型命名而非本身的名稱
- 考慮使用此結構的對象(人?電腦?)
- 定義命名格式
- 對標籤使用同一詞性
- 命名考慮排序方便性
把資料儲存在結構化的檔案目錄之中
將文字儲存到資料庫中將圖像儲存到資料庫中1
2
3
4//LIB_mysql
insert()
update()
exe_sql()
將圖檔轉成blob1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 透過Base-64編碼
$data_array['IMAGE'] = base64_encode(file_get_contents($file_path));
// 顯示資料庫內圖檔
<img src="show_image.php?img_id=6">
// show_img.php
<?
include("LIB_mysql.php");
$image_id = $_GET['img_id'];
$sql = "select IMAGE from table where IMAGE_ID='".$image_id."'";
list($img) = exe_sql(DATABASE, $sql);
header("Content-type: image/jpeg");
echo base64_decode($img);
exit;
?>
- 把資料變小一點
- 儲存指向資料的參照
- 壓縮資料
對傳進來的檔案進行壓縮:1
2
3
4
5
6// 送出可接受壓縮檔的請求
$header[] = "Accept-Encoding:compress, gzip";
curl_setopt($curl_session, CURLOPT_HTTPHEADER, $header);
// 對壓縮檔進行解壓縮
$uncompressed_file = gzuncompress($compressed_file); - 移除不需要的格式
使用strip_tags()移除HTML標籤 - 為大型圖像檔案建立縮圖,或建立比較小的呈現方式
- 運用縮圖
1
2
3
4
5
6//利用LIB_thumbnail函式庫
$org_file = "test.jpg";
$new_file_name = "thumbnail.jpg";
$max_width = 90;
$max_height = 90;
create_thumbnail($org_file, $new_file_name, $max_width, $max_height);
Part II 案例分享
Chapter 8. 價格監視用網路機器人
- 設計一個能解析語意的script腳本
- 目標網頁的初始化與下載
ref: chapter8_price_monitoring_bot.php
Chapter 9. 圖像擷取用網路機器人
- 圖像擷取用網路機器人範例
相同檔案名稱、不同目錄 - 建立圖像擷取用網路機器人
ref: chapter9_image_capture_bot.php
Chapter 10. 鏈結查證用網路機器人
無效鏈結的偵測(Link-Verification)
- 建立一個鏈結查證用網路機器人
HTTP Code | 類別 | 意義 |
---|---|---|
100-199 | 訊息相關 | 一般未使用 |
200-299 | 成功 | 請求成功 |
300-399 | 重導向 | 頁面被移走了 |
400-499 | 客戶端錯誤 | 客戶端發出錯誤請求 |
500-599 | 伺服器錯誤 | 伺服器錯誤 |
1 |
|
- 網路機器人的運行
1
2
3
4
5
6// LIB_http_codes
include(LIB_http_codes.php)
echo $status_code_array[$YOUR_HEEP_CODE]['MSG'];
//LIB_resolve_address
resolve_address($link, $page_base);
Chapter 11. 搜尋排名用網路機器人
- 對一個搜尋結果頁面進行描述
付費區域/組織過的結果(SEO結果)
“下一頁”的位置 - 搜尋排名用網路機器人的工作方式
輸入”關鍵字”與”要找的頁面”,尋找排名結果:頁面.筆數 - 搜尋排名用網路機器人的執行
- 搜尋排名用網路機器人的工作原理
- 變數初始化
- 使用”關鍵字”於搜尋引擎進行搜索
- 跳過網告與導覽文字
- 檢查搜尋頁面是否出現於結果中
- 報告結果
- 搜尋排名用網路機器人的script腳本
ref: chapter11_search_ranking_bot.php
插入解析(insertion parse):於資料內部插入自定義的tag(如<data>) - 最終想法
善待你的資料來源
搜尋網站對待網路機器人時,可能與瀏覽器不同
讓網路蜘蛛搜刮搜尋引擎的資料,可不是好主意 - 進一步的探索
Chapter 12. 彙整用網路機器人
範例應用:Google Map結合房地產資訊,顯示彙整結果頁面
- 為網路機器人選擇資料的來源
API或RSS - 彙整用網路機器人的範例
RSS饋送資料的方式1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// RSS feed
<title>
RSS Feed Title
</title>
<link>
www.Link_to_web_page.com
</link>
<description>
Description of RSS feed
</description>
<copyright>
Copyright notice
</copyright>
<lastBuildDate>
Date of RSS publication
</lastBuildDate>
// RSS Item
<item>
<title> Title of Item </title>
<link> URL of associated web page for item </link>
<description> Description of item </description>
<pubDate> Publication date of item </pubDate>
</item>
ref: chapter12_aggregation_bot.php
CDATA: XML用CDATA標籤來識別不應該被解釋為XML的標籤
<![[…文字…]]>
- 在你的彙整用網路機器人中加入篩選的功能
- 進一步的探索
Chapter 13. FTP網路機器人
- FTP網路機器人範例
ref: chapter13_ftp_bot.php - PHP與FTP
PHP支援的一般FTP指令
FTP函式($ftp:FTP File Stream) | 用法 |
---|---|
ftp_cdup($ftp) | 使附目錄變成目前的目錄 |
ftp_chdir($ftp, “directory/path”) | 改變目前的目錄 |
ftp_delete($ftp, “filename”) | 刪除某個檔案 |
ftp_get($ftp, “local file”, “remote file”, MODE) | 將遠端的檔案拷貝到本機檔案,MODE: FTP_ASCII/FTP_BINARY |
ftp_mkdir($ftp, “directory name”) | 建立一個新的目錄 |
ftp_rename($ftp, “file name”) | 在FTP伺服器上更改檔案或目錄名稱 |
ftp_put($ftp, “remote file”, “local file”, MODE) | 將本機的檔案拷貝至遠端的檔案,MODE: FTP_ASCII/FTP_BINARY |
ftp_rmdir($ftp, “directory/path”) | 移除一個目錄 |
ftp_rawlist($ftp, “directory/path”) | 送回一個陣列,元素為檔案訊息 |
- 進一步的探索
Chapter 14. 能讀取電子郵件的網路機器人
- POP3協定
利用telnet登入POP3郵件伺服器讀取郵件:1
telnet mail.server.net 110
- LIST指令取得編號
- RETR <編號>:讀取內容
刪除郵件: - DELE <編號>
- QUIT //執行後才真正刪除
RSET <編號>:QUIT前可還原刪除動作
利用網路機器人來執行POP3協定
利用PHP的opensocket()、fputs()和fgets()執行POP3指令
ref. chapter14_email_reading_bot.php進一步的探索
不相容系統之間的介面:發送檔案至mailbox讓機器人讀取後處理
Chapter 15. 能發送電子郵件的網路機器人
- 電子郵件、網路機器人與垃圾郵件
避免成為垃圾郵件指導原則:
- 允許收件人取消訂閱
- 避免多個重複的郵件
- 使用恰當的標題
- 表明你自己的身份
- 遵守法律規定
- 利用SMTP與PHP來發送郵件
編輯php.ini配置檔
關閉郵件伺服器的中繼傳輸(relay host)功能,避免成為垃圾郵件跳板
PHP的mail()函式利用LIB_mail發送格式化的郵件1
2
3
4$email_address = "account@someserver.com";
$email_subject = "SUBJECT";
$email_message = "MESSAGE";
mail($email_address, $email_subject, $email_message);
LIB_mail地址種類 | 功能 | 必要或選擇 |
---|---|---|
To | 主要收件人地址 | 必要 |
Reply-to | 回覆地址 | 選擇 |
Return-path | 無法傳送時,通知地址 | 選擇 |
From | 寄件人地址 | 必要 |
Cc | 其他收件人 | 選擇 |
Bcc | 密件副本 | 選擇 |
- 編寫一個能發送電子郵件通知的網路機器人
網頁內容變化時,發送電子郵件的網路機器人:別讓垃圾郵件篩選程式,篩選掉合法郵件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29include("LIB_http.php");
include("LIB_mysql.php");
include("LIB_mail.php");
$webbot_email_address = "mail@server.com";
$notification_email_address = "mail@server.com";
$target_web_site = "www.website.com";
$download_array = http_get($target_web_site, $ref="");
$web_page = $download_array['FILE'];
$new_signature = sha1($web_page);
$sql = "select SIGNATURE from signatures where WEB_PAGE='".$target_web_site"'";
list($old_signature) = exe_sql(DATABASE, $sql);
if($new_signature != $old_signature){
if(isset($data_array)) unset($data_signature);
$data_array['SIGNATURE'] = $new_signature;
update(DATABASE, $table="signatures", $data_array, $key_column="WEB_PAGE", $id=$target_web_site);
$subject = $target_web_site."內容改變";
$message = $subject."\n";
...
$address['from'] = $webbot_email_address;
$address['replayto'] = $webbot_email_address;
$address['to'] = $notification_email_address;
formatted_mail($subject, $message, $address, $content_type="text/plain");
}
確保from與reply-to是相同網域
發送HTML格式化的電子郵件
- 利用formatted_mail()函式
- 設定$content_type為text/html
- 使用完整形式的URL
- 使用標準格式技術(如:table)
- 避免使用CSS
- 將訊息建立成一個字串
- 進一步的探索
Chapter 16. 將某個網站功能轉換成函式
- 撰寫一個函式的介面
提交郵遞區號,回傳詳細資訊
ref. chapter16_website_to_function_bot.php - 最終的想法
- 分配資源:利用多台伺服器的資源
- 使用標準介面:跨平台的能力
- 設計一個自訂的輕量級”網路服務”
Part III 進階技術的相關考量
Chapter 17. 網路蜘蛛
網路蜘蛛: Spider, web spider, crawlers, web walker
網路蜘蛛的工作原理
seed URL 抓取第一個頁面(第一滲透層the first penetration level),重複抓取直到最大滲透層網路蜘蛛的範例
ref. chapter17_simple_spider.phpLIB_simple_spider
harvest_links($url):下載指定的網頁,回傳link array
archive_links($spider_array, $penetration_level, $temp_link_array):標記level與排除exclusion_list中的url
get_domain($url):抓取根網域
exclude_link($spider_array, $link):排除不需要的鏈結利用網路蜘蛛進行一些實驗
三個警告:
- $FETCH_DELAY至少設定1~2秒以避免DoS
- 滲透層的最大值保持1或2避免記憶體用盡
- 使用terminal進行,不要透過瀏覽器
加上負載程式
實際要執行的程式內容進一步的探索
- 將鏈結儲存到資料庫中
- 將取得鏈結的程式,與負載程式區隔開來
- 利用多部電腦分散工作
- 規範管理頁面請求
Chapter 18. 採購用網路機器人與狙擊程式
- 採購用網路機器人理論
流程:
取得採購商品的條件 -> 買家身份認證 -> 對採購項目進行確認
-> 價格可接受嗎?/庫存有需求嗎?/非買不可嗎? -> 進行採購
-> 評估結果 -> 完成 - 狙擊程式(Sniper)理論
利用時間作為觸發事件的機器人
流程:
取得採購商品的條件 -> 買家身份認證 -> 對採購項目進行確認
-> 時鐘同步 -> 出價的時間點到了嗎? -> 送出你的報價
-> 評估結果 -> 完成
取得伺服器時間設定:
1 |
|
- 對你自己的網路機器人與狙擊程式進行測試
- 進一步的探索
- 最終的想法
Chapter 19. 網路機器人與密碼術
- 設計一個能使用加密功能的網路機器人
1
http_get("https://...", $referer)
- 對Web網路加密的快速綜覽
handshake過程確認使用的加密演算法,客戶端取得伺服器端回傳的CA(Certificate authority)、公鑰等資訊,客戶端使用公鑰進行加密回傳,伺服器利用回傳的訊息建立session憑證。
忽略認證動作:
1 |
|
設定認證動作:
1 |
|
- 最終的想法
使用正確的協定,表單action有可能為http/https,
Chapter 20. 身份證認
身份認證是什麼?
證明你是誰的過程script腳本範例與練習網頁
練習網頁:
身份認證方法 | 練習網頁的位置 |
---|---|
基本身份認證 | http://www.WebbotsSpidersScreenScrapers.com/basic_authentication |
Cookies Sessions | http://www.webbotsspidersscreenscrapers.com/cookie_authentication |
Query Sessions | http://www.webbotsspidersscreenscrapers.com/query_authentication |
帳號密碼:webbot / sp1der3
基本身份認證
realm(領域):受保護的範圍,一般來說為當前的伺服器目錄,以及子目錄下的所有網頁。
基本身份證認的缺點:
除了關閉瀏覽器,沒有其他登出的方法。
表單外觀無法改變(根據瀏覽器實作)。
明碼傳送資訊,安全性低。(可透過digest authentication補強,加入128-bits MD5,但支援度低)。
ref. chapter20-1_basic_authentication.phpsession認證
兩種方法:cookie與query string
Cookie Session進行身份認證
Cookie的工作原理:
cookie於HTTP header中,當client端向server端發出請求時,檢查cookie值是否正確。
若不正確則伺服器向使用者要求憑證並將session值保存於cookie中。
ref. chapter20-2_cookie_session_authentication.php
以Query Session進行身份認證
有些瀏覽器限制cookie使用。
ref. chapter20-3_query_session_authentication.php
- 最終的想法
需要搭配加密傳輸。
留意登入條件不要隨意散播,防止留下紀錄。
網站可能結合多種認證,確認所有認證方案。
Chapter 21. 進階的Cookie管理
- Cookie的工作原理
網際網路為無狀態(stateless)環境
Cookie兩種類型:
- 臨時性(temporary)
- 持久性(Permanent) 透過Http Header傳送cookie
1
2setcookie("TemporaryCookie", "66");
setcookie("PermanentCookie", "88", time()+3600);
PHP/CURL和Cookie
1
2
3
4//讀取cookie
include("LIB_http.php"); //define("COOKIE_FILE", "c:\cookie.txt");
$target="http://www.WebbotSpidersScreenSrapers.com/Listing_21_1.php"
http_get($target, "");不同瀏覽器維護自定義的cookie結構,瀏覽器間的cookie不相容。
Cookie對網路機器人設計帶來了什麼挑戰?
cookie可以由使用者關閉,非強制項目。
在cookie傳遞的資料與Get/Post傳遞的內容一樣重要。
清除臨時性Cookie
PHP/CURL將cookie寫入檔案,需要自行檢查是否過期。
或者設定下列屬性:1
curl_setopt($s, CURLOPT_COOKIESESSION, TRUE);
管理多使用者的Cookie
1 |
|
- 進一步的探索
- 設計可讀取header的script,增加cookie管理能力。
- 若無法在運行伺服器上寫入檔案,可以寫入DB。
- 自動刪除臨時性cookie的script。
- 透過瀏覽器巨集自動管理cookie。
Chapter 22. 網路機器人與網路蜘蛛排程
- 為網路機器人排程,做好準備工作
使用批次檔 - Windows XP工作排程器
系統工具>工作排程器 - Windows 7工作排程器
控制台>工作排程器 - 不以日曆為基礎的觸發方式
使用e-mail進行觸發1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22include("LIB_pop3.php");
define("SERVER", "your.mailserver.net");
define("USER", "your@email.com");
define("PASS", "your_passeord");
$webbot_path = "C:\\webbots\\view_competitor.bat";
$connection_array = POP3_connect(SERVER, USER, PASS);
$POP3_connection = $connection_array['handle'];
if($POP3_connection){
$email_array = POP3_list($POP3_connection);
for($xx=0; $xx<count($email_array); $xx++){
list($mail_id, $size) = expode(" ", $email_array[$xx]);
$message = POP3_retr($POP3_connection, $mail_id);
if(stristr($message, "Subject: Run the webbot")){
$output = shell_exec($webbot_path);
echo "<pre>$output</pre>";
POP3_delete($POP3_connection, $mail_id);
}
}
} - 最終的想法
- 為機器人訂出最恰當的執行週期
- 避免單點故障
- 增加排成變化的多樣性
Chapter 23. 使用瀏覽器巨集擷取難度較高的網站
AJAX前,微軟的ActiveX落實XMLHTTP應用,搭配DHTML可提供毋須更新頁面的內容更新。
2006年W3C建立AJAX官方標準
- 有效擷取網站資料時所遇到的障礙
AJAX:URL與內容不再是一對一關係。
可能難以達到以下工作:
- 將滑鼠游標移到某個日曆上,然後選定一個日期
- 捲動圖像側邊欄,選定某個特定的縮圖
- 用拖放的方式選擇某個物件
- 緩慢的輸入文字到文字框中,等待拼字檢查器給我們拼字的建議
怪異的JavaScript和Cookie行為:某些情況下,網頁利用JavaScript建立另一個JavaScript,最終被用來寫入cookie或是控制表單行為。或者網頁會將圖像寫入cookie。
Flash:內部為封閉的環境
- 運用瀏覽器巨集,克服網路資料擷取的障礙
使用script腳本來控制瀏覽器的動作。
iMacros瀏覽器巨集:
建議指令1
2
3
4
5
6
7
8' 註解的寫法
SET !TIMEOUT 240
SET !ERRORIGNORE YES //忽略錯誤訊息
SET !EXTRACT_TEST_POPUP NO
FILTER TYPE=IMAGES STATUS=ON
CLEAR
TAB T=1
TAB CLOSEALLOTHERS - 最終的想法
Chapter 24. 深度應用iMacros
- 深入到iMacros中,添加額外的功能
寫一個script動態建立瀏覽器巨集
利用iMacros載入本地端網站伺服器網頁
不使用iMacors腳本引擎(付費版)的原因:
此腳本以COM為基礎,跨平台性較差
雖然可以接受本機檔案,但與資料庫或其他網站的外部資料無發搭配很好
並沒有其他好處
建立動態巨集
範例:競品價格追蹤
- 使用iMacors和動態巨集,寫一個能模擬實際瀏覽器使用者的網路機器人。
- 開發一個能讀取內部資料庫的PHP script腳本,找出銷售最佳的前100項商品,然後寫出一個合適的巨集,取得這些商品在競爭者那邊所賣的價格。
- 寫個能從競爭者網頁中解析出價格的PHP script腳本。
寫一個能建立動態巨集的script腳本
1 |
|
將外部資料整合到動態建立的巨集中
1 |
|
自動執行iMacros巨集
在windows中啟動iMacros
1 |
|
在Linux中啟動iMacros
1 |
|
- 進一步的探索
其他技巧:
- 將firefox設為預設瀏覽器,且不做其他用途
- 多個iMacros script不能在同一個桌面帳號執行,必須錯開時間,或者錯開使用者
- 可能需要登入安全網站,多瞭解iMacros對登入憑證加密的能力
- IE版的iMacros不能支援分頁的功能
Chapter 25. 部署與規模擴展
- 一對多的環境
一個機器人接受多個輸入資源
可以試著運用平行運算 - 一對一的環境
難以擴展規模
最大的挑戰在於如何避免機器人被當作具有攻擊意圖的對象 - 多對多的環境
可能是同一個script腳本的多個實體 - 多對一的環境
最難以擴展的架構
不小心就會發動DoS攻擊 - 規模擴展與服務阻斷攻擊
避免不小心發動了DoS
就算是很簡單的網路機器人,也能塞爆網站
目標網站本身沒效率
規模越擴展,問題越嚴重:尤其多對一架構可能造成目標網站癱瘓,但是優點是可以使用多個IP位置 - 為一個網路機器人建立多個執行實體
三種方法:
- 用fork的方法複製出另一個額外的process
- 在作業系統中建立同一個script的多個實體
- 在多個硬體上執行相同的網路機器人:機器人網路(Botnet)
- Botnet的管理
Botnet的溝通方式:與管理的伺服器進行溝通,管理伺服器進行工作安排
以Polling的方式與Botnet伺服器溝通
1
2
3
4
5
6
7<?php
include('LIB_http.php');
$post_array['STATUS'] = "TASK REQUEST";
$post_array['BOT'] = "this webbot's name";
$post_array['VERSION'] = "script version level";
$botnet_server_address = "https://.BOTNET_SERVER_ADDRESS";
$reply = http_post_form($botnet_server_address, $post_array);判斷是否有工作要執行
伺服器先判斷網路機器人的身份(名稱與憑證),衡量伺服器負載能力。Checkout程序
伺服器指派工作給網路機器人,設定時限。指派工作
透過XML格式提供訊息1
2
3
4
5
6
7<XML>
<TASK_ID>9999</TASK_ID>
<TIMESTAMP>...</TIMESTAMP>
<TARGET>www.SomeWebSite.com</TARGET>
<USERNAME>username</USERNAME>
<PASSWORD>password</PASSWORD>
</XML>解析Botnet伺服器回傳的訊息
1
2
3
4
5
6<?php
$task_id = return_between($reply['PAGE'], "<TASK_ID>", "</TASK_ID>", EXCL);
$target = return_between($reply['PAGE'], "<TARGET>", "</TARGET>", EXCL);
$username = return_between($reply['PAGE'], "<USERNAME>", "</USERNAME>", EXCL);
$password = return_between($reply['PAGE'], "<PASSWORD>", "</PASSWORD>", EXCL);
?>沒任務的範例
1
2
3
4<XML>
<TASK_ID>NO TASK</TASK_ID>
<TIMESTAMP>...</TIMESTAMP>
</XML>執行工作
將擷取到的資料上傳給伺服器
1
2
3
4
5
6
7<?php
include<'LIB_http.php');
$post_array['STATUS'] = "DATA_COLLECTED";
$post_array['BOT'] = "this webbot's name";
$post_array['VERSION'] = "script version level";
$botnet_server_address = "https://".BOTNET_SERVER_ADDRESS;
$reply = http_post_form($botnet_server_address, $post_array);處理擷取到的資料
將回傳資料保存在資料結構或者資料庫中。
伺服器可能會留下一些log。
- 進一步的探索
如何增加待完成工作列表到Botnet伺服器?:透過API輸入?
Botnet伺服器的最大能力?
掩人耳目的網路機器人,使用代理或其他技術?
自動從伺服器下載軟體更新。
Part IV 比較大的考量
Chapter 26. 能掩人耳目的網路機器人
為什麼要設計出能掩人耳目的網路機器人?
避免被當作駭客攻擊:
Log記錄檔案的三種類型:存取log紀錄、錯誤log紀錄、自訂log紀錄
Log監視軟體“掩人耳目”,就意味著要模仿人類的行為模式
善待你的資料來源
選擇在比較繁忙時,執行你的網路機器人
別老是在每天的同一個時間,執行你的網路機器人
別在假期和週末執行你的網路機器人
在取得網頁和網頁之間,插入隨機的延遲時間最終的想法
Chapter 27. 代理伺服器
- 什麼是代理伺服器
代理你做某件事的某個東西 - 在虛擬世界中的代理伺服器
列印機代理伺服器、內容過濾伺服器、防火牆 - 為什麼網路機器人的開發者要使用代理伺服器
運用代理伺服器達到匿名的效果
使用代理伺服器可以假裝你在別的地方 - 使用代理伺服器
在瀏覽器中使用代理伺服器
透過PHP/CURL來使用代理伺服器1
2
3// $session_id = curl_init()
curl_setopt($session_id, CURLOPT_PROXY, $proxy_ip.": ".$proxy_port);
curl_setopt($session_id, CURLOPT_PROXY_TYPE, CURLPROXY_SOCKS5); //default: CURL_PROXY_HTTP - 代理伺服器的種類
開放式代理伺服器(open proxy)
開放式代理伺服器的種類:
透明代理伺服器:通常會將IP位置放在HTTP_X_FORWARDED_FORWARDED變數中
匿名代理伺服器:不會紀錄原始IP,不過仍然看偵測出經由代理伺服器轉送
假冒代理伺服器:試圖隱藏真實伺服器
開放式代理伺服器的黑暗面:
很少是正當理由開放,有可能是政府機關/私人監控,或者私人電腦中毒。
關於開放式代理伺服器清單服務的更多訊息:
有提供開放代理伺服器清單的服務公司。Tor
使用Tor:需要安裝Polipo(執行於電腦中的代理伺服器)
設定PHP/CURL使用Tor:port為8118
Tor的缺點:
無法保證完全匿名,網站可能透過JavaScript或瀏覽器外掛跳過Tor的作用。
速度較慢。商業化代理伺服器
例如:Anonymizer(http://www.Anonymizer.com)、HideMyIP(http://HideMyIP.com)
- 最終的想法
匿名只是一種有幫助的做法,而不是一種絕對有效的功能
建立自己的代理伺服器
Chapter 28. 具有容錯能力的網路機器人
- 具有容錯能力的網路機器人,幾種不同的類型
####適應URL的改變:
- 只下載目標網站中確實可取得的頁面
避免對已經不存在的頁面提出請求:
透過HTTP代碼檢查
1 |
|
檢查連結路徑
確保經由正確路徑進入,而非已過期的連結
利用使用者名稱,確認表單提交結果
1 |
|
- 能隨著標頭的重導向,轉移到已被更新過的頁面
HTTP標頭包含location:URL1
2curl_setopt($curl_session, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($curl_session, CURLOPT_MAXREDIRS, 4);
<head>標籤之間的頁面重導向
範例:
1 |
|
ref. chapter28-1_meta_tag_redirection
- 只搜尋head tag
- 在meta tag中搜尋http-equiv屬性
- 重導向的URL被轉換為一個完整的解析地址
- 找到第一個重導向指令後,script就會停止
透過JavaScript的重導向
1 |
|
透過JavaScript的重導向可能會很複雜,不容易被解析(例如function呼叫)。
- 能引用參照的值,指出你所跟隨的連結,是來自於某個仍然存在於網站上的頁面
維護引用參照值的正確性。
####適用頁面內容的改變:
- 避免位置解析:可能由於網頁排版改變而無法運作
- 使用相對解析:找出關鍵元素後,再尋找關聯的資訊
- 尋找那些不太可能會發生變化的界標:改變頻率最低的大多是與伺服器應用有關的部分(type=”hidden”的資料,或者元素id等)
####適應表單中的改變:
先進行表單診斷
檢查表單變數,包含:使用的method、action、名稱與資料
ref. chapter28-2_form_parser.php
####適應cookie的改變:
LIP_http函式庫並不會自動刪除過期的cookie
####適應網路斷線與網路壅塞的狀況:
設定time-out值:
1 |
|
PHP延長超時設定
1 |
|
錯誤處理程式
錯誤訊息記錄應該包含以下內容:哪一個網路機器人出問題?為什麼出問題?
出問題的日期與時間?1
2
3
4
5
6
7
8
9function webbot_error_handler($failure_mode){
$email_address = "your.account@someserver.com";
$email_subject = "Webbot Failure Notification";
$email_message = "Webbot T-Rex encountered a fatal error<br>";
$email_message = $email_message.$failure_mode."<br>";
$email_message = $email_message."at".date("r")."<br>";
mail($email_address, $email_subject, $email_message);
exit;
}為機器人增加狀態,執行前檢查是否需要執行,若發生錯誤時透過error handler改變狀態
以移除排程。進一步的探索
Chapter 29. 對網路機器人友善的網站設計
針對搜尋引擎的網路蜘蛛,進行網頁的最佳化(搜尋引擎最佳化, SEO)
定義良好的鏈結
Google Bombs與Spam Indexing:針對特定網站,利用相同的鏈結文字描述建立出多個鏈結
Title標籤
Meta標籤
標題標籤(h1~h6)
圖像的alt屬性會妨礙到搜尋引擎網路蜘蛛的網頁設計技術
JavaScript:執行前難以被辨認
非ASCII內容:如Flash設計”僅含資料”的介面
可擴展標記語言(XML)(ref. chapter29-1_xml_parser.php)
輕量級資料交換:需注意安全性問題(如使用eval()直接將回傳內容保存為變數的做法)
ref. chapter29-2_light-weight_data_exchange_interface.php
簡單物件存取協定(SOAP):
1 |
|
SOAP優點:跨平台
SOAP缺點:門檻較高
REST(Representational State Transfer)
- 最終的想法
Chapter 30. 獵殺網路蜘蛛
網站擁有者可能為了下面幾種目的,希望隔絕網路機器人:
保護智慧財產
保護自己的電子郵件地址
規範管理網站的使用頻率
避免放在網路上的媒體被人保存起來
為所有使用者建立公平競爭的環境
和善的提出要求
建立服務條款協定
使用robots.txt檔案
使用Robots Meta標籤1
2
3<head>
<meta name="robots" content="noindex, nofollow">
</head>建立速度上的障礙
選擇性允許某些網路代理程式,進行存取動作:記得在伺服器端進行檢查
使用擾亂(obfuscation)的做法
使用cookie、加密、JavaScript與重導向
使用者身份認證
經常更新你的網站(改變元素順序、表單方法、檔案名稱、參考點文字)
將文字嵌入到其他媒體中,如CAPTCHA(Completely Automated Public Turing test to tell Computers and Humans Apart)。 破解:http://decaptcher.com設下陷阱
建立一個捕捉網路蜘蛛的陷阱:人類無法進行的操作1
<a href="spider_trap.php"><img src="spacer.gif" width="0" height="0"></a>
對不想要的網路蜘蛛,能做的一些好玩的事
策略 | 相應做法 |
---|---|
驅逐 | 記錄IP之後進行阻擋 |
限制存取 | 記錄IP之後限制可存取的資源 |
誤導 | 將網路蜘蛛重導到另一個頁面中 |
分析 | 識別IP(如:http://www.arin.net),追蹤擁有者 |
忽略 | 忽略所有自動化操作 |
- 最終的想法
Chapter 31. 讓你的網路機器人遠離是非
- 一切都源自於尊重
網站資源都是擁有者付費並非免費資源 - 版權
確實向各方進行諮詢
暸解版權法的一些基本概念:
版權並不需要經過註冊的程序
在預設的情況下,創作總是”保留所有權利”
不能對一個事實,主張擁有其版權
如果能以具有創造性的方式,呈現整群的事實,就可以主張擁有版權
在合理使用法(Fair Use Laws)的規範下,可使用部分的內容素材 - 侵入動產
過度消耗目標伺服器的頻寬,影響效能或其他人的使用 - 網際網路的相關法律
維吉尼亞洲反垃圾郵件法(anti-spam) - 最終的想法
Appendix A. PHP/CURL參考資料
- 建立一個最精簡的PHP/CURL Session
1
2
3
4
5
6
7
8<?
$s = curl_init();
curl_setopt($s, CURLOPT_URL, "http://www.schrenk.com");
curl_setopt($s, CURLOPT_RETURNTRANSFER, TRUE);
$downloaded_page = curl_exec($s);
curl_close($s);
?> - 初始化PHP/CURL Session
1
curl_init();
- PHP/CURL選項設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19curl_setopt($s, CURLOPT_URL, "http://www.schrenk.com"); //定義目標網站
curl_setopt($s, CURLOPT_RETURNTRANSFER, TRUE); //以字串回傳結果
curl_setopt($s, CURLOPT_REFERER, "http://www.domain.com/index.php"); //設定參照網址
curl_setopt($s, CURLOPT_FOLLOWLOCATION, TRUE); //跟隨網站重導向(僅header內容,不包含refresh meta或JavaScript中的設定),需設定CURLOPT_MAXREDIRS
curl_setopt($s, CURLOPT_MAXREDIRS, 4); //最大重導向次數
curl_setopt($s, CURLOPT_USERAGENT, "Webbot"); //設定代理程式名稱
curl_setopt($s, CURLOPT_NOBODY, TRUE); //排除body部分
curl_setopt($s, CURLOPT_HEADER, TRUE); //包含標頭(預設不包含)
curl_setopt($s, CURLOPT_TIMEOUT, 30); //設定timeout值,單位秒
curl_setopt($s, CURLOPT_COOKIEFILE, "c:\bots\cookies.txt"); //讀取cookie檔案
curl_setopt($s, CURLOPT_COOKIEJAR, "c:\bots\cookies.txt"); //寫入cookie檔案
curl_setopt($s, CURLOPT_HTTPHEADER, ["Mime-Version:1.0", "Content-type: text/html; charset=iso-8859-1", "Accept-Encoding: compress, gzip"]); //配置HTTP header
curl_setopt($s, CURLOPT_SSL_VERIFYPEER, FALSE); //設定是否使用客戶端憑證
curl_setopt($s, CURLOPT_USERPWD, "passwd"); //設定身份認證密碼
curl_setopt($s, CURLOPT_UNRESTICTED_AUTH, TRUE); //若有設定重導向需要開啟
curl_setopt($s, CURLOPT_POST, TRUE); //使用POST
curl_setopt($s, CURLOPT_POSTFIELDS, "var1=1&var2=2"); //設定POST內容
curl_setopt($s, CURLOPT_VERBOSE, FALSE); //關閉詳細模式
curl_setopt($s, CURLOPT_PORT, 234); //設定使用的port - 執行PHP/CURL指令
1
2
3curl_exec();
curl_getinfo(); //檢索PHP/CRUL Session訊息
curl_error(); //回傳可能發生在PHP/CURL session期間的錯誤 - 關閉PHP/CURL Session
1
curl_close();