有朋友問到:
“我需要得到一個web page的title,因為這個title一般都比較靠前,只要取得html 的前面少量內容就可以了。因為要取得很多個頁面的title,如果下載整個html code, 肯定比較浪費時間。.net好像沒有現成的類可以干這件事情(取得部分html) ,我應該如何去實現?”
一種比較"廉價"(即較小成本條件下)的解決思路:
第一步:取出含有頁面title部分的最小集合。這是“廉價”的關鍵!
第二步:用正則表達式取出<title>和</title>之間的部分即可。
先看下效果:
下面我們來分析:
頁面title 一般都在靠近開始處,所以我們從開始讀取Stream流,(如果靠近結尾,則如何?)讀取到什么地方為止呢?有個比較明顯的標志是
</title>
遇到它結束就可以了。
以什么方式讀取,我這里選取的是:逐行讀取,取到標志符即終止。
方法如下:
<!-- {cps..2}-->
#region
獲取所需要的頁面內容
///
<summary>
///
獲取所需要的頁面內容bytony2009.9,16
///
邀月(downmoon):3w@live.cn
///
<paramname="strUrl">
所要查找的遠程網頁地址
</param>
///
<paramname="timeout">
超時時長設置,一般設置為8000
</param>
///
<paramname="enterType">
是否輸出換行符,0不輸出,1輸出文本框換行
</param>
///
<paramname="EnCodeType">
編碼方式
</param>
///
<returns></returns>
public
static
string
GetRequestString(
string
strUrl,
int
timeout,
int
enterType,EncodingEnCodeType)
{
if
(strUrl.Equals(
"
about:blank
"
))
return
null
;;
if
(
!
strUrl.StartsWith(
"
http://
"
)
&&
!
strUrl.StartsWith(
"
https://
"
)){strUrl
=
"
http://
"
+
strUrl;}
string
strResult
=
string
.Empty;
System.IO.StreamReadersr
=
null
;
string
temp
=
string
.Empty;
try
{
HttpWebRequestmyReq
=
(HttpWebRequest)HttpWebRequest.Create(strUrl);
myReq.Timeout
=
timeout;
myReq.UserAgent
=
"
User-Agent:Mozilla/5.0(compatible;MSIE6.0;WindowsNT5.2;SV1;.NETCLR2.0.40607;.NETCLR1.1.4322;.NETCLR3.5.30729)
"
;
myReq.Accept
=
"
*/*
"
;
myReq.KeepAlive
=
true
;
myReq.Headers.Add(
"
Accept-Language
"
,
"
zh-cn,en-us;q=0.5
"
);
HttpWebResponseHttpWResp
=
(HttpWebResponse)myReq.GetResponse();
if
(HttpWResp.StatusCode
==
System.Net.HttpStatusCode.OK)
{
StringBuilderstrBuilder
=
new
StringBuilder();
StreammyStream
=
HttpWResp.GetResponseStream();
sr
=
new
StreamReader(myStream,EnCodeType);
string
tmp
=
string
.Empty;
while
((temp
=
sr.ReadLine())
!=
null
)
{
strBuilder.Append(temp);
//
ifhas</title>thenendbydownmoon(邀月)2009.9.16
tmp
=
strBuilder.ToString();
if
(tmp.IndexOf(
"
</title>
"
)
>
0
){
break
;}
if
(enterType
==
1
){strBuilder.Append(
"
/r/n
"
);}
}
strResult
=
strBuilder.ToString();
return
strResult;
}
return
string
.Empty;
}
catch
(Exceptionex)
{
//
#regionLoghandlebyTony2008.11.21
return
strResult;
//
#endregion
}
finally
{
if
(sr
!=
null
){sr.Close();}}
}
#endregion
取出后就是再用正則取出<title>和</title>之間的部分。
這部分浪費了些時間,因為邀月的正則功底不行啊!·
先后試過如下正則表達式:
<!-- {cps..5}-->
1
//
stringstrRegEx="<[^>]*>";
2
//
stringstrRegEx="<title>.*([^</title>])";
3
//
stringstrRegEx="<title>(.*?)</title>";
4
//
stringstrRegEx="<title>.*?</title>";
均不能達到想要的“經濟廉價”的效果,最終,找到這個:
<!-- {cps..8}-->
public
static
string
GetContextByHtml(
string
sHtml)
{
//
stringregex="(<title[>])(.*)(<//title>)";
string
regex
=
@"
(?<=<title.*>)([/s/S]*)(?=</title>)
"
;
System.Text.RegularExpressions.Regexex
=
new
System.Text.RegularExpressions.Regex(regex,System.Text.RegularExpressions.RegexOptions.IgnoreCase);
return
ex.Match(sHtml).Value.Trim();
}
演示效果如上圖:
后續問題:
1、將繼續實現代理方式躲過IP;
2、將嘗試另外一種通過Request.Filter方式直接替換來實現。
歡迎交流。
助人等于自助! 3w@live.cn
以一種"廉價"的方式獲取頁面的標題(downmoon)