| 具體實現思路: 1 首先用WebClient類下載網頁源碼 public static string DownLoadHtml(string url) ??????? { ??????????? string output = ""; ??????????? Encoding encode = Encoding.Default; ??????????? WebClient webclient = new WebClient(); ??????????? try ??????????? { ??????????????? webclient.Headers.Add("Referer", url); ??????????????? byte[] buff = webclient.DownloadData(url); ??????????????? output = encode.GetString(buff); ??????????? } ??????????? catch ??????????? { ??????????? } ??????????? return output; ??????? } 需要注意的: 有的網頁可能下不下來,有種種原因比如需要cookie,編碼問題等等 這是就要具體問題具體分析比如在頭部加入cookie webclient.Headers.Add("Cookie", cookie); 這樣可能需要一些重載方法。根據需要寫就可以了。 2 下一步過濾掉不必要的特殊字符,把下載下來的網頁內容清干凈,方便抓取(比如空格雙引號) 過濾特殊字符 public static string RepalceStr(string str) ??????? { ?????????? ??????????? str = str.Replace("\r\n", ""); ??????????? str = str.Replace("\"", ""); ??????????? str = str.Replace(":", ""); ??????????? str = str.Replace("\t", ""); ??????????? str = str.Replace(" ", ""); ??????????? str = str.Replace("'", ""); ??????????? str = str.Replace("\r", ""); ??????????? str = str.Replace("\n", ""); ??????????? return str; ??????? } 3最后也是最重要的即從目標字符串的第begin個字符處開始,讀取以 strBegin 開頭, strEnd 結束的字符串.并返回獲取到的內容,如果不存在,返回空。 public static string GetHTMLContent(string strTarget, string strBegin, string strEnd, ref int begin) ??????? { ??????????? string result; ??????????? int posBegin, posEnd; ??????????? posBegin = strTarget.IndexOf(strBegin, begin); ??????????? if (posBegin != -1) ??????????? { ??????????????? posEnd = strTarget.IndexOf(strEnd, posBegin + strBegin.Length); ??????????????? if (posEnd > posBegin) ??????????????? { ??????????????????? result = strTarget.Substring(posBegin, posEnd + strEnd.Length - posBegin); ??????????????????? begin = posEnd + strEnd.Length; ??????????????????? return result; ??????????????? } ??????????? } ??????????? begin = -1; ??????????? return ""; ??????? } 需要注意的: begin是引用類型,有可能一段網頁中可能會有重復的關鍵詞 比如<!--文章標題-->,<!--文章標題-->,如果你想對第二個文章標題里的內容 操作那么begin就派上用場了,他每次抓取完都返回抓取內容的結尾,在調用 此方法就可以得到第二個<!--文章標題-->的內容。 在抓取完的數據一般都存在數據庫中,如果是一個表直接存放就可以了. 如果是兩個表比如新聞名稱和新聞內容分開,這是你就需要用到sql server的一個全局變量 Select @@IDENTITY;它可以標識生成記錄的唯一ID。以用作插入新聞內容用。(兩個表以 news_id關聯) 4 因為是精確抓取在程序處理的過程中要用到很多正則,比如去除連接去除括號等,這當然是 簡單的正則了。 (見到有高手說動態生成正則還沒弄懂學習之~) Regex pattern1 = new Regex("<a.*?</a>", RegexOptions.Singleline | RegexOptions.IgnoreCase); Regex pattern2 = new Regex("(.*?)", RegexOptions.Singleline | RegexOptions.IgnoreCase); newscontent = pattern1.Replace(newscontent, ""); newscontent = pattern2.Replace(newscontent, ""); 程序里除了主要的方法外用得最多的就屬正則表達式了,處理字符串用正則表達式那是當仁不 讓,。 5 下面是抓取時一些特殊情況的處理: 1比如新聞只讓抓當日的 static DateTime todaysdate = DateTime.Now.Date; //date為抓取的日期 DateTime newsday = Convert.ToDateTime(date); newsday = newsday.Date; TimeSpan s = todaysdate - newsday; if (s.TotalDays.ToString() == "0") ???? { ??? 這里干活 ???? } 2過濾特殊字符比如url里有bbs關鍵字的不抓 if (newsurl.IndexOf("bbs") > 0) { ????? continue; } 3寫入新聞唯一id到文件避免同一天抓兩次數據引起新聞重復(再抓的時候比較就可以了) FileStream fs = new FileStream(filepaths, FileMode.OpenOrCreate, FileAccess.Write); StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.GetEncoding("gb2312")); sw.Flush(); sw.BaseStream.Seek(0, SeekOrigin.Begin); //唯一id sw.Write(newsqid); sw.Close();?? 6抓數據的時候可以把要抓的網站和一些關鍵字寫入xml一邊程序里直接調用 這樣比較省時省力,比如: <?xml version="1.0" encoding="utf-8" ?> <GetDatas> <MyData> <CarUrl>http://www.webhost/mysite.html</CarUrl> ??? <CarFilterf><![CDATA[列表頁特征字符串開始]]></Filterf> ??? <CarFilters><![CDATA[列表頁特征字符串結束]]></Filters> ??? <CarDetailFilterf><![CDATA[詳情頁特征字符串開始]]></CarDetailFilterf> ??? <CarDetailFilters><![CDATA[詳情頁特征字符串結束]]></CarDetailFilters> ??? <NewsKey>種類一</NewsKey> </MyData> <MyData> ??? <CarUrl>http://www.webhost/mysite.html</CarUrl> ??? <Filterf><![CDATA[列表頁特征字符串開始]]></CarFilterf> ??? <Filters><![CDATA[ 列表頁特征字符串結束 ]]></CarFilters> ??? <DetailFilterf><![CDATA[詳情頁特征字符串開始]]></CarDetailFilterf> ??? <DetailFilters><![CDATA[詳情頁特征字符串結束]]></CarDetailFilters> ??? <NewsKey>種類二</NewsKey> </CarData> <MyData> 程序里根據newskey的種類寫入數據庫方便調用。 7最后就是寫入數據庫了,可以以上面xml里newskey的鍵值插入數據庫。
|