有時候,如果我們想抓取其他人的網頁並擷取部份資料下來,應該怎麼做呢?其實,在 ASP.NET 中已經提供了足夠的工具,一點都不困難。以下的程式共需要四個參數...
有時候,如果我們想抓取其他人的網頁並擷取部份資料下來,應該怎麼做呢?其實,在 ASP.NET 中已經提供了足夠的工具,一點都不困難。
以下的程式共需要四個參數:
URL:指定要被搜尋的網頁
Filter:要尋找什麼特定字串
StartTag:如果找到上述字串後,還要再往下找什麼字串
EndTag:如果找到上述字串後,要再找什麼字串
使用範例:Response.Write(MineURL("http://tw.f4.page.bid.yahoo.com/tw/auction/d11001870", "目前出價:", "<TD><b>", " 元</b></TD>"))
☆注意:上面這個網址其實並不存在,我只是放在上面做個例子而已。
上面範例是到 Yahoo 拍賣的某一個拍賣頁中尋找「目前出價:」這個字串,在它後面是目前最高出價的金額,例如 3,000 元,而我們要取出 "3,000"。但如果檢視 HTML 原始碼,會發現該網頁在「目前出價:」字串之後其實還有 <TD><b> 這兩個 Tag,所以必須指定 StartTag 為 "<TD><b>"。在我們最終所想取出的 "3,000" 這一字串之後,則有 " 元</b></TD>",因此必須指定為 EndTag。
如果網頁改變而導致字串搜尋不到,那麼程式會傳回相關的回應訊息。
以下提供一個 C# 版本:
using System.Net;
...
string mineUrl(string url, string filter, string startTag, string endTag)
{
WebClient myWebClient = new WebClient();
string body = myWebClient.DownloadString(URL);// Search web body for requested filter string
int offFound = body.IndexOf(filter);
if (offFound <= 0)
return "<a href=" + url + ">Filter not found!</a>";
else
{
int findNextStart = body.IndexOf(startTag, offFound);
if (findNextStart <= 0)
return "<a href=" +url+ ">StartTag not found!</a>";
else
{
int findNextEnd = body.IndexOf(endTag, findNextStart + startTag.Length);
if (findNextStart <= 0)
return "<a href=" + url + ">EndTag not found!</a>";
else
return body.Substring(findNextStart + startTag.Length, findNextEnd - findNextStart - startTag.Length);
}
}
}
或許有人會覺得奇怪, 既然要找的字串是 StartTag 和 EndTag 中間所包含的部份, 為什麼還需要先找到 Filter 所代表的字串? 這是因為在 HTML 中有太多重複出現的元素, 例如 <p>, <tr>, <td> 等等; 如果我們先找到一個特定字串(Filter), 再從此特定字串開始, 往後找到下一個特定字串(StartTag), 再找到 EndTag, 如此就可以大幅減少尋找的難度。
如果網頁內重複的標簽實在太多, 即使使用上述方法也不足以精準的擷取到所要的文字時, 那麼我們就必須重複擷取的動作多次。當然, 抓網頁內全部文字的動作只需做一次, 其後的分析則可以做好幾次, 視實際需要而定。
你應該知道, 以上這個程式非常依賴搜尋的關鍵字眼(即 Filter, StartTag 和 EndTag)的正確性。如果原始網站做了任何改動(例如把 "<td>" 改成 "<td style=..."), 你就需要重新設定。所以你在決定關鍵字眼時必須好好考慮, 讓它的容忍度愈大愈好, 例如把 "<td>" 改成 "<td" 等等, 如此你才不需時常修改這些關鍵字眼。當然, 這就得看來源網站的特性而定了。
換個角度想, 如果你不願意別人使用這種自動化程式來抓取你的網頁, 你該怎麼辦? 其實我還真的看過不少網站動了很多手腳來阻止別人這麼做。有很多網頁也許不是刻意的, 但你就是抓不到, 例如 ASP.NET 所產生的網頁, 一旦經過 PostBack 後, 你就抓不到了, 因為你只能抓到 PostBack 之前的內容。還有一些網頁則是刻意進行擾亂的, 因為它會在內容中插入許多肉眼看不到的隨機字元(它把這些字元以白色顯示, 所以肉眼看不見), 使得你即使抓得到, 也是一堆垃圾。這些做法應該都是有效的(至少可以用來防止這裡所介紹的手法)。