簡單C#信息采集工具實現
最近想整只爬蟲玩玩,順便熟悉下正則表達式。
開發環境 vs2008 sql2000
實現方法如下
1.先抓取網頁代碼
2.通過正則匹配出你需要的內容
比如http://www.soso.com/q?w=%C4%E3%BA%C3&pg=1 頁面中 搜索結果的標題跟連接地址。具體可以根據你的需要填寫合適的地址跟正則。
3.把匹配出的內容保存到數據庫中。對其中的數據可以根據需要自己進行處理
具體實現代碼
1.讀取網頁的代碼
public static string GetDataFromUrl(string url)
{
string str = string.Empty;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
//設置Http頭;
request.AllowAutoRedirect = true;
request.AllowWriteStreamBuffering = true;
request.Referer = "";
request.Timeout = 10 * 1000;
//request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)";
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
//根據http應答頭來判別編碼
string Characterset = response.CharacterSet;
Encoding encode;
if (Characterset != "")
{
if (Characterset == "ISO-8859-1")
{
Characterset = "gb2312";
}
encode = Encoding.GetEncoding(Characterset);
}
else
{
encode = Encoding.Default;
}
//聲明一個內存流來貯存http應答流
Stream Receivestream = response.GetResponseStream();
MemoryStream mstream = new MemoryStream();
byte[] bf = new byte[255];
int count = Receivestream.Read(bf, 0, 255);
while (count > 0)
{
mstream.Write(bf, 0, count);
count = Receivestream.Read(bf, 0, 255);
}
Receivestream.Close();
mstream.Seek(0, SeekOrigin.Begin);
//從內存流里讀取字符串這里涉及到了編碼方案
StreamReader reader = new StreamReader(mstream, encode);
char[] buf = new char[1024];
count = reader.Read(buf, 0, 1024);
while (count > 0)
{
str += new string(buf, 0, 1024);
count = reader.Read(buf, 0, 1024);
}
reader.Close();
mstream.Close();
}
}
catch (Exception ex)
{
GetDataFromUrl(url);
}
finally
{
if (response != null)
response.Close();
}
return str;
}
2.正則匹配的代碼
public static ArrayList GetString(string reg, string content)
{
Regex r = new Regex(reg, RegexOptions.Compiled);
MatchCollection matches = r.Matches(content);
ArrayList a = new ArrayList();
foreach (Match m in matches)
{
string[] arr = new string[10];
arr[0] = m.Groups[1].Value;
arr[1] = m.Groups[2].Value;
arr[2] = m.Groups[3].Value;
arr[3] = m.Groups[4].Value;
arr[4] = m.Groups[5].Value;
arr[5] = m.Groups[6].Value;
arr[6] = m.Groups[7].Value;
arr[7] = m.Groups[8].Value;
arr[8] = m.Groups[9].Value;
arr[9] = m.Groups[10].Value;
a.Add(arr);
}
return a;
}
3.如果抓取的頁面很多 ,可以把多線程跟隊列應用過來,提高抓取效率
Queue<int> numbers = new Queue<int>();
const int MaxCount = 5;//同時運行的最多線程數
private static object _lock = new object();
private void Test()
{
while (true)
{
int i = 0;
lock (_lock)
{
if (numbers.Count == 0)
{
flag = false;
return;
}
i = numbers.Dequeue();
}
f(i);
}
}
void Ssss()
{
for (int i = 1; i <= 100; i++)//處理的頁面參數 從http://www.soso.com/q?w=你好&pg=1 到http://www.soso.com/q?w=你好&pg=100
{
numbers.Enqueue(i);
}
for (int i = 0; i < MaxCount; i++)
{
Thread thread = new Thread(new ThreadStart(Test));
thread.Name = "T" + i.ToString();
thread.Start();
}
}
private void f(int num)
{
string str = ClassLibrary1.Class1.GetDataFromUrl("http://www.soso.com/q?w=%C4%E3%BA%C3&pg="+num);
string reg = "<a href=/"([^/"]+?)/" [^>]+? target=/"_blank/">([//s//S]+?)</a>";
ArrayList a = ClassLibrary1.Class1.GetString(reg, str);
for (int i = 0; i < a.Count; i++)
{
string[] arr = (string[])a[i];
Result r = new Result();
r.Value1 = arr[0];
r.Value2 = ClassLibrary1.Class1.Html2Txt(arr[1]);
ResultManager.AddResult(r);
}
}
5.常用的一些正則表達式
* 0-多個
? 0-1個
+ 1-多個
+? 盡可能少的匹配
*? 0次或多次,盡可能少
/w 等效於 [a-zA-Z_0-9]
/W 匹配非單詞
/S 非空
/s 等效於 [ /f/n/r/t/v] 空格,制表 換頁
. 匹配除了換行以為的任何字符
/d 數字
[^>] 除了>以為的字符
[/u4e00-/u9fa5] 漢字
6.代碼只是實現了信息采集的主要功能,根據你自己的需要更換采集頁面,跟合適的正則表達式后,可以根據你的需要自動進行采集,對采集到的數據,再根據你的需要自己進行處理。
7.數據庫操作部分用的3層代碼生成器連接地址 在 app.config中
如果你發現有什么不合理的,需要改進的地方,郵件聯系328452421@qq.com(qq常年不在線,郵件聯系)朱曉 。相互交流 謝謝
順便問下 有家是新泰的沒。