1. 程式人生 > >C#程式設計之多執行緒爬蟲程式

C#程式設計之多執行緒爬蟲程式

一、簡單介紹:
技術方面主要包括:
(1)技術選型:
1) 課程設計使用的開發語言是C#。
2)課程設計選用了檔案流方式獲取網站資料。
3)課程設計使用多執行緒抓取網頁程式碼。
4)課程設計使用了正則表示式對原始碼進行解析處理。

(2)程式執行流程:
通過圖示可以更形象的瞭解程式執行的整個流程:
1)程式首先下載網站首頁的原始碼
2)對首頁原始碼進行分析,提取出網站建設類目下的連結並存儲到佇列中。
3)運用多執行緒,分別同時下載佇列中的連結。
4)利用正則表示式對下載的連結原始碼進行分析。提取圖片的URL並下載圖片。擷取需要的文字資訊。
5)儲存下載的文字和圖片。把下載分析連結的資訊顯示在操作介面上。

程式的整體流程:
這裡寫圖片描述

二、再貼程式碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using
System.Diagnostics; namespace crawlWebsiteAndExtractInfo { public partial class frmCrawlWebsite : Form { public static Queue<String> q = new Queue<string>(); public static string[] surl = new string[100]; //照片冗餘 public static int a = 0; public static
int j = 0; //public static int m = 0; public static bool b = false; public static object locker = new object();//新增一個物件作為鎖 public static object locker1 = new object(); public static object locker2 = new object(); public static object locker3 = new object(); public static Stopwatch watch = new Stopwatch(); public static bool flag=true; public static string textbox = string.Empty; public int Num=5; //string[] surl = new string[300]; public frmCrawlWebsite() { InitializeComponent(); } private void btnCrawlAndExtract_Click(object sender, EventArgs e) { //獲得網址 //http://www.hyzbi.com string urlToCrawl = txbUrlToCrawl.Text; //HTTP請求 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlToCrawl); //GET方法 req.Method = "GET"; //獲得HTTP回覆 HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); //定義編碼方式 string htmlCharset = "utf-8"; //編碼方式 Encoding htmlEncoding = Encoding.GetEncoding(htmlCharset); StreamReader sr = new StreamReader(resp.GetResponseStream(), htmlEncoding); //顯示html內容 string respHtml = sr.ReadToEnd(); rtbExtractedHtml.Text = respHtml; } private void btnExtractInfo_Click(object sender, EventArgs e) { //找到網站建設類目下面的連線 string h1userP = @"/portal/article/index/cid/19/id/(\d+)"; //捕獲匹配 MatchCollection foundH1user = (new Regex(h1userP)).Matches(rtbExtractedHtml.Text); foreach (Match m in foundH1user) { string url = "http://www.hyzbi.com" + (string)m.Value; q.Enqueue(url); } Thread[] downloadThread;//聲名下載執行緒 downloadThread = new Thread[21];//為執行緒申請資源,確定執行緒總數 //int i=0; // richTextBox1.Text = "aaa"; watch.Start(); for (int i = 0; i <Num; i++) { ThreadStart startDownload = new ThreadStart(DownLoad); //ParameterizedThreadStart startDownload = new ParameterizedThreadStart(DownLoad); downloadThread[i] = new Thread(startDownload);//指定執行緒起始設定 downloadThread[i].Start();//逐個開啟執行緒 } //while (q.Count != 0) ; } public delegate void ProcessDelegate(); public void richTextShow(string ss) { string s=ss; richTextBox1.Text=s; } public void picture(string rrh) { string rh = rrh; string pp = @"src\s*=\s*[""']?([^'"" >]+?)[ '""][^>]*?>"; MatchCollection found = (new Regex(pp)).Matches(rh); foreach (Match mm in found) { string urll = "http://www.hyzbi.com" + (string)mm.Groups[1].Value; int id = Array.IndexOf(surl, urll); //exists = ((IList)surl).Contains(urll); if (id == -1) { surl[a] = urll; a++; try { Bitmap img = null; HttpWebRequest req = (HttpWebRequest)(WebRequest.Create(urll)); req.Method = "GET"; HttpWebResponse res = (HttpWebResponse)(req.GetResponse()); img = new Bitmap(res.GetResponseStream()); lock (locker3) { img.Save(@"e:/c/" + a + ".jpg"); } //m++; } catch (Exception ee) { } } } } // public void picture save() public string wenben(string rrh) { string rh = rrh; //抓取標題 //string hstrOutput=null; string bt = @"<h2>(.*)</h2>"; //StreamWriter sw = new StreamWriter("e:/b.txt", true); //MatchCollection bbt = (new Regex(bt)).Matches(rh); Match nnn = (new Regex(bt)).Match(rh); // foreach (Match nn in bbt) //{ //richTextBox1.Text += nn.Value + "\n"; Regex hregex = new Regex("<.+?>", RegexOptions.IgnoreCase); string hstrOutput = hregex.Replace(nnn.Value, "");//替換掉"<"和">"之間的內容 hstrOutput = hstrOutput.Replace("<", ""); hstrOutput = hstrOutput.Replace(">", "\r"); hstrOutput = hstrOutput.Replace(" ", ""); // sw.WriteLine(hstrOutput); // sw.WriteLine("\n"); // } string p = @"<p.*>(<span .*>)?(.*)(</span>)?</p>"; MatchCollection tp = (new Regex(p)).Matches(rh); lock (locker) { StreamWriter sw = new StreamWriter("e:/b.txt", true); sw.WriteLine(hstrOutput); sw.WriteLine("\n"); //StreamWriter sw = new StreamWriter("e:/b.txt", true); //string p = @"<p.*>(<span .*>)?(.*)(</span>)?</p>"; //MatchCollection tp = (new Regex(p)).Matches(rh); foreach (Match n in tp) { Regex regex = new Regex("<.+?>", RegexOptions.IgnoreCase); string strOutput = regex.Replace(n.Value, "");//替換掉"<"和">"之間的內容 strOutput = strOutput.Replace("<", ""); strOutput = strOutput.Replace(">", "\r"); strOutput = strOutput.Replace(" ", ""); //sw.WriteLine(n.Groups[0].Value); sw.WriteLine(strOutput); sw.WriteLine("\n"); } sw.Close(); } return hstrOutput; } public void DownLoad() { while (true) { string url; string h2; if (q.Count != 0) { lock (locker1) { url = q.Dequeue(); j++; } //richTextBox1.Text = url; try { HttpWebRequest rr = (HttpWebRequest)WebRequest.Create(url); rr.Method = "GET"; HttpWebResponse resp = (HttpWebResponse)rr.GetResponse(); string htmlCharset = "utf-8"; Encoding htmlEncoding = Encoding.GetEncoding(htmlCharset); StreamReader sr = new StreamReader(resp.GetResponseStream(), htmlEncoding); string rh = sr.ReadToEnd(); picture(rh); h2 = wenben(rh); lock (locker2) { ProcessDelegate showProcess = delegate() { richTextBox1.AppendText(url + h2 + DateTime.Now.ToString() + "\n"); }; richTextBox1.Invoke(showProcess); } } catch (Exception eee) { } } else { /* flag = false; watch.Stop(); string time = watch.ElapsedMilliseconds.ToString(); ProcessDelegate showTime = delegate() { richTextBox1.AppendText("共用時" + time + "\n"); }; richTextBox1.Invoke(showTime);*/ break; } } } // } private void button1_Click(object sender, EventArgs e) { //string path1 = @"e:\c"; //開啟D盤下的log.txt檔案 //System.Diagnostics.Process.Start(path1); string path2 = @"e:\c"; //呼叫資源管理器,開啟e盤下的c資料夾 System.Diagnostics.Process.Start("explorer", path2); } private void button2_Click(object sender, EventArgs e) { string path1 = @"e:\b.txt"; System.Diagnostics.Process.Start("explorer",path1); } private void button3_Click(object sender, EventArgs e) { try { textbox = this.textBox1.Text; Num = Convert.ToInt32(textbox); } catch (Exception eee) { } } } }

三、多說一點:
(1)檔案流方式:
C#中通常有三種方法獲取網頁內容。第一種方式為:使用webclient、第二種方式為:webBrowser、第三種方式為HttpWebRequest/HttpWebResponse
。此次程式設計中選用的是第三種方式即HttpWebResquest/HttpWebResponse方式。這是一種比較通用的獲取方式。
(2)c#中的多執行緒:
在Visul C#中System.Threading 名稱空間提供一些使得可以進行多執行緒程式設計的類和介面,其中執行緒的建立有以下三種方法:Thread、ThreadPool、Timer。
本次課程設計中選用的是Thread方式。這也許是最複雜的方法,但它提供了對執行緒的各種靈活控制。首先你必須使用它的建構函式建立一個執行緒例項,它的引數比較簡單,只有一個ThreadStart 委託:
public Thread(ThreadStart start);
然後呼叫Start()啟動它。
(3)正則表示式:
在編寫處理字串的程式或網頁時,經常會有查詢符合某些複雜規則的字串的需要。正則表示式就是用於描述這些規則的工具。換句話說,正則表示式就是記錄文字規則的程式碼。
在此次課程設計中,使用了正則表示式對網頁的原始碼進行擷取和分析,以獲得想要的資料資訊。
程式流程詳解:
(1)程式使用檔案流方式從首頁hyzbi.com中下載整個頁面的原始碼。
(2)通過使用正則表示式,將網站建設類目下的網頁URL擷取下來,並儲存在一個佇列中。
(3)啟用多執行緒,每個執行緒中從佇列中拿取一個URL。此時此時使用了互斥鎖,避免執行緒衝突。執行緒每拿取一個URL就將佇列中的URL記錄刪除,避免重複下載。執行緒中同樣運用檔案流的方式下載網頁URL的原始碼。並封裝了兩個函式,分別對應圖片和文字的下載分析。
當執行緒工作完成時,將完成時間以及完成專案顯示在操作介面上。
(4)對於圖面的解析,使用正則表示式擷取網頁URL中所有的圖片URL。把圖片URL儲存在陣列中,美獲得一個URL就和陣列中的項比較,有重複項就捨棄,無重複項就下載,這樣就做到了圖片的冗餘,避免下載重複的圖片。
(5)對於文字的解析,則使用了正則表示式的擷取和替代。在文字的儲存上,也加了一個互斥鎖,使同一時刻只有一個執行緒可以訪問本地檔案儲存文字。
四、程式執行結果:
1、主程式介面
這裡寫圖片描述
2、爬取的網站中的圖片資訊:
這裡寫圖片描述
3、爬取的網站中的文字資訊:
這裡寫圖片描述

四、更多瞭解:
完整的程式碼及設計說明我已上至資源,手戳這裡是連結兒
【注】程式中指定了爬取的網站網址
不知為什麼貼的程式碼,移動端看,csdn的編輯器會出亂碼???
我看了一下,電腦上看,顯示的程式碼是正確的,最好把程式碼從我的資源中下下來看,沒有問題。

相關推薦

C#程式設計執行爬蟲程式

一、簡單介紹: 技術方面主要包括: (1)技術選型: 1) 課程設計使用的開發語言是C#。 2)課程設計選用了檔案流方式獲取網站資料。 3)課程設計使用多執行緒抓取網頁程式碼。 4)課

C語言執行機制(程式可以同時被執行而不會相互干擾)

接觸過linux的人或多或少知道,linux有多執行緒的機制,也就是說程式可以同時執行,不受干擾,關於這個在我以前的博文裡有過類似模擬的時間片輪轉程式,跟這個其實是類似的。其實在window上,執行緒的標頭檔案也是可以包含進來使用的,我這裡用DevC++這個軟體來測試,看看

Liunx C 程式設計執行與Socket

多執行緒 pthread.h是linux特有的標頭檔案,POSIX執行緒(POSIX threads),簡稱Pthreads,是執行緒的POSIX標準。該標準定義了建立和操縱執行緒的一整套API。在類Unix作業系統(Unix、Linux、Mac OS X等)中,都使用Pthreads作為作業系統的執行緒。

Linux 下 C 網路程式設計 執行通訊 例項

簡單示例,有不對的地方,歡迎指點。 伺服器端 /* ============================================================================ Name : sockThreadServer

併發程式設計執行執行安全

什麼是執行緒安全? 為什麼有執行緒安全問題? 當多個執行緒同時共享,同一個全域性變數或靜態變數,做寫的操作時,可能會發生資料衝突問題,也就是執行緒安全問題。但是做讀操作是不會發生資料衝突問題。 案例: 需求現在有100張火車票,有兩個視窗同時搶火車票,請使用多執行緒模擬搶票效果。 p

併發程式設計執行基礎

執行緒與程序區別 每個正在系統上執行的程式都是一個程序。每個程序包含一到多個執行緒。執行緒是一組指令的集合,或者是程式的特殊段,它可以在程式裡獨立執行。也可以把它理解為程式碼執行的上下文。所以執行緒基本上是輕量級的程序,它負責在單個程式裡執行多工。通常由作業系統負責多個執行緒的排程和執行。

Python併發程式設計執行使用

目錄 一 開啟執行緒的兩種方式 二 在一個程序下開啟多個執行緒與在一個程序下開啟多個子程序的區別 三 練習 四 執行緒相關的其他方法 五 守護執行緒 六 Python GIL(Global Interpreter Lock) 七 同步鎖 八 死鎖現象

Java網路程式設計4.UDP網路程式設計執行優化

UDP網路程式設計之多執行緒優化——DatagramSocket類 1、UDP網路程式設計之多執行緒優化的思想 (1)一個執行緒實現客戶端——傳送資料 (2)一個執行緒實現伺服器端——接收資料

併發程式設計執行基礎-Thread和Runnable的區別及聯絡(二)

上篇文章講述了建立執行緒的常用方式 本篇主要分析一下Thread和Runnable兩種方式建立執行緒的區別及聯絡 聯絡: ▶Thread類實現了Runable介面。 ▶都需要重寫裡面Run方法。 區別: ▶Thread方式不支援多繼承,Runnable方式支援多個實現 ▶Runnable更容易實

併發程式設計執行基礎-執行五種狀態(三)

原文地址:https://www.cnblogs.com/wangyichuan/p/5990821.html 執行緒從建立、執行到結束總是處於下面五個狀態之一:新建狀態、就緒狀態、執行狀態、阻塞狀態及死亡狀態。     1.新建狀態(New):         當用new操作符建立一個執行緒時,

Python學習【第24篇】:死鎖,遞迴鎖,訊號量,Event事件,執行Queue python併發程式設計執行2------------死鎖與遞迴鎖,訊號量等

python併發程式設計之多執行緒2------------死鎖與遞迴鎖,訊號量等 一、死鎖現象與遞迴鎖 程序也是有死鎖的 所謂死鎖: 是指兩個或兩個以上

Python學習【第23篇】:利用threading模組開執行 python併發程式設計執行1

python併發程式設計之多執行緒1 一多執行緒的概念介紹 threading模組介紹 threading模組和multiprocessing模組在使用層

併發程式設計執行

一、什麼是執行緒 在傳統作業系統中,每個程序有一個地址空間,而且預設就有一個控制執行緒 執行緒顧名思義,就是一條流水線工作的過程,一條流水線必須屬於一個車間,一個車間的工作過程是一個程序 車間負責把資源整合到一起,是一個資源單位,而一個車間內至少有一個流水線  流水線的工作需要電源,電源就相當於cpu 所以,

PHP 高階程式設計執行-訊息佇列

1. 多執行緒環境安裝 1.1. PHP 5.5.9 安裝PHP 5.5.9 https://github.com/oscm/shell/blob/master/php/5.5.9.sh ./configure --prefix=/srv/php-5.5.9 \ --wi

python併發程式設計執行理論部分

一 什麼是執行緒     在傳統作業系統中,每個程序有一個地址空間,而且預設就有一個控制執行緒   執行緒顧名思義,就是一條流水線工作的過程,一條流水線必須屬於一個車間,一個車間的工作過程是一個程序       車間負責把資源整合到一起,是一個資源單位,而一個車間內至少有一個流水線       流水線

socket網路程式設計執行阻塞IO例項

先介紹一下網路層次結構、socket與TCP/UDP之間的關係。同步、非同步,阻塞、非阻塞的區別。 網路由下往上分為物理層、資料鏈路層、網路層、傳輸層、會話層、表示層和應用層。 IP 協議對應於網路層,TCP協議對應於傳輸層,HTTP協議對應於應用層,三者從本質上來說沒有可

Java網路程式設計執行Client-Server

前面廢話過了,現在就直接看程式碼吧! ThreadedClient.java package exercise01; import java.io.*; import java.net.*; public class ThreadedClient { privat

Python網路程式設計執行

多執行緒 多執行緒舉例: import threading from time import sleep,ctime def sing(): for i in range(3): print("正在唱歌...%d"%i)

C++筆記執行的理解與應用

一、執行緒與程序 程序,擁有資源並且獨立執行的基本單位; 將CPU比作是是一個工廠,那麼程序可以看做是一個可以獨立進行工作的車間,車間內有生產必須的資源以及工人,同時工廠內同一時刻只有一個車間在開工,但是工廠內是可以有多個車間的。[1] 執行緒,程式執行的

Linux下socket程式設計執行TCP伺服器

程式碼如下: thread_server.c #include<string.h> #include<stdlib.h> #include<stdio.h> #include<sys/types.h> #i