一步一步教你抓數據——用.net精確提取網站數據的通用方法

具體實現思路:

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 下一步過濾掉不必要的特殊字符,把下載下來的網頁內容清乾淨,方便抓取(比如空格雙引號)
過濾特殊字符

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的鍵值插入數據庫。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章