接到一個任務是把中國名牌網站的某些內容添加到我們的網站上,地址如下:
http://www.chinamp.org/mppro2.php
這個頁上全是一些文章連結清單,點選連結會出現文章的詳細內容顯示頁,根據這個規律,結合Regex,XMLHTTP技術,Jscript服務端指令碼,以及ADO技術,寫了一個小程式,把這些內容抓取到了本機資料庫。抓取下來,然後就資料庫對資料庫導資料就比較方便了。先建立一個Access資料庫,結構如下
Id
自動編號
標識,主鍵
oldID
數字
舊資料編碼
Title
標題
文本
Content
備忘
內容
具體實現代碼如下
<%@LANGUAGE="JSCRIPT" CODEPAGE="936"%>
<!-- METADATA NAME="Microsoft ActiveX Data Objects 2.5 Library"
TYPE="TypeLib" UUID="{00000205-0000-0010-8000-00AA006D2EA4}" -->
<%
//開啟資料庫
try
{
var strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("#db.mdb");
var objConnection = Server.CreateObject("ADODB.Connection");
objConnection.Open(strConnectionString);
}
catch(e)
{
Response.Write(e.description);
Response.End();
}
%>
<script language="jscript" runat="server">
//遠程擷取資料
function GetData()
{
var xHttp = new ActiveXObject("microsoft.xmlhttp");
xHttp.open("POST","http://www.chinamp.org/mppro2.php",false);
xHttp.send();
return(xHttp.responseText);
}
//利用Regex提取合格連結
function GetLinks(str)
{
var re = new RegExp("<a[^<>]+?/>((.|/n)*?)<//a>", "gi");
var a = str.match(re); //第一次搜尋
for(var i=0;i<a.length;i++)
{
var t1,t2;
var temp;
var r = /qy.php/?id=(/d+)/ig;
if(!r.test(a))continue;
temp = a.match(/qy.php/?id=(/d+)/ig);
t1 = RegExp.$1;
temp = a.match(/<font[^<>]+?color=/"#000000/"/>(.*?)<//font>/ig);
t2 = RegExp.$1;
if(t1 == t2)continue;
SaveArticle(t1,t2,GetContent(t1));
}
}
//通過提取的連結擷取ID,並通過這個ID取抓取相應的文章
function GetContent(id)
{
var xHttp = new ActiveXObject("microsoft.xmlhttp");
xHttp.open("POST","http://www.chinamp.org/qy.php?id=" + id,false);
xHttp.send();
var str = xHttp.responseText;
var re = new RegExp("<span[^<>]+?style=/"font-size:10/.8pt/">(.*?)<//span>", "gi");
var a = str.match(re);
return(RegExp.$1);
}
//入庫
function SaveArticle(oldID,Title,Content)
{
var oRst = Server.CreateObject("ADODB.Recordset");
var sQuery;
sQuery = "SELECT oldID,Title,Content FROM Articles"
oRst.Open(sQuery,objConnection,adOpenStatic,adLockPessimistic);
oRst.AddNew();
oRst("oldID") = oldID;
oRst("Title") = Title;
oRst("Content") = Content;
oRst.Update();
oRst.Close();
Response.Write(Title + "抓取成功" + "<br>");
}
</script>
<HTML>
<HEAD>
<TITLE> 抓取文章</TITLE>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"></HEAD>
<BODY>
<%=GetLinks(GetData())%>
</BODY>
</HTML>
下一步就是,把這個Access的資料庫的內容匯入到伺服器的資料庫裡了,但是還有一些東西,就是原來的文章是分類的,所以匯入的時候還得手工分類,因為在分析連結的時候Regex本來寫就很麻煩,但還算嚴謹,如果把分類也用Regex解析的話,會很麻煩,因為分類是包含在<td>裡面的,而那個頁的<td>標籤又很多,要想定位分類文字所在的<td>會很麻煩,即便寫出來,程式也會失去靈活性,變得難以維護,所以現在只做到了這一步。
如何用Regex提出網頁表格中的資料?
<table[^>]*>[/s/S]*?<a[/s/S]*?href=("(?<href>[^"]*)"|'(?<href>[^']*)'|(?<href>[^>/s]*))[^>]*?>(?<title>[/s/S]*?)</a>[/s/S]*?</table>
測試:
string content = @"<table border=""0"" width=""11%"" class=""Headline"">
<tr>
<td width=""100%"">
<p align=""center"">這是第一個表格</td>
<td>
<A href=""http://www.163.com"" target=_blank>網易</A></td>
</tr>
</table>";
Regex htmlRegex = new Regex(
@"<table[^>]*>[/s/S]*?<a[/s/S]*?href=(""(?<href>[^""]*)""|'(?<"
+ @"href>[^']*)'|(?<href>[^>/s]*))[^>]*?>(?<title>[/s/S]*?)</a>["
+ @"/s/S]*?</table>",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
//content = htmlRegex.Replace(content, "");
MatchCollection mc = htmlRegex.Matches(content);
string[] div = new string[mc.Count];
for (int i=0; i<mc.Count; i++)
{
//int n = Int32.Parse(mc[i].Groups["Content"].Value);
Console.WriteLine(mc[i].Groups[0].Value); //The whole table
Console.WriteLine(mc[i].Groups["href"].Value); //URL
Console.WriteLine(mc[i].Groups["title"].Value); //Text
//Console.WriteLine();
//div[i] = mc[i].Groups["content"].Value;
}
輸出:
<table border="0" width="11%" class="Headline">
<tr>
<td width="100%">
<p align="center">這是第一個表格</td>
<td>
<A href="http://www.163.com" target=_blank>網易</A></td>
</tr>
</table>
http://www.163.com
網易