1. 程式人生 > >C# 爬取靜態網頁入門

C# 爬取靜態網頁入門

目錄

確定目標內容和目標站點

分析目標站點結構

網頁獲取

網頁節點解析

分析天氣網頁結構

總結


爬蟲分為兩種,靜態網頁爬蟲和動態網頁爬蟲,相比較於動態網頁爬蟲而言很簡單,靜態網頁的爬取不需要執行如JavaScript類似的程式碼,只需要獲取頁面Html程式碼,並解析目標內容即可,本文介紹了靜態網頁爬取的基本流程。

確定目標內容和目標站點

明確需求,比如本文中需要爬取北京過去一段時間內的所有天氣,首先找一個合適的網站,比如http://www.tianqihoubao.com,在該網站中,可以找到北京歷史天氣的站點http://www.tianqihoubao.com/lishi/beijing.html

分析目標站點結構

在瀏覽器中開啟北京歷史天氣站點後,不能直接獲得天氣,而是獲得了許多超連結,其中有指向不同時間段的天氣連結,因此,需要解析這個頁面以分析出目標連結。

目標站點中有兩類連結,一類是目標連結,另一類是其他連結。接下來在瀏覽器中按F12檢視網頁的原始碼,檢查目標連結的特點,這些特點有可能是Html節點或者Html屬性,總之需要找到一個特點來區分目標連結和其他連結。

Html程式碼中,可以看到連結的兩個區別

  • 兩種連結的節點層次是不一樣的,目標連結中有div#content 其他連結中沒有,因此可以根據節點的不同來選取連結,即選取有id屬性值為content的節點;
  • 最後的<a>節點中屬性href的取值是不同的,目標連結總是含有"month",而其他連結中沒有,因此可以根據最後一個節點的屬性href的值含有"month"來選取連結。

網頁獲取

位於System.Net空間下的WebClient可以方便地獲取網頁,主要程式碼如下

public static string GetHtml(string url)
{
    string res = "";
    WebClient client = new WebClient();
    Stream stream = client.OpenRead(url);
    StreamReader sr = new StreamReader(stream, Encoding.Default);
    res = sr.ReadToEnd();
    sr.Close();
    client.Dispose();
    return res;
}

網頁節點解析

這裡有一個大名鼎鼎的庫HtmlAgilityPack來輔助我們將字串的網頁html程式碼生成Dom樹,並且讓我們可以快速方便選取Dom樹的節點,以完成在上節中的思路。VS開啟工具->NuGet包管理器->管理解決方案的Nuget包,從這裡可以搜尋HtmlAgilityPack包進行相應的安裝。在使用這個庫時,需要引入HtmlAgilityPack名稱空間。

using HtmlAgilityPack;

接下來,採取上節中的第二種思路來解析出目標連結。

  • 選擇Dom樹中所有含有href屬性的<a>節點,這會把所有超連結的節點都選擇出來,包括目標連結和其他連結;
  • 遍歷所有連結節點,檢查href屬性的值是否以"/lishi/beijing/month"開頭,是則加入連結集合
public static List<string> ParseLink(string html)
{
    List<string> res = new List<string>();
    var doc = new HtmlDocument();
    doc.LoadHtml(html);
    var linkNodes = doc.DocumentNode.SelectNodes("//a[@href]");
    foreach (var linkNode in linkNodes)
    {
        string link = linkNode.GetAttributeValue("href", "");
        if (link.StartsWith("/lishi/beijing/month"))
        {
            res.Add(link);
        }
    }
    return res;
}

至此已經解析出該站點所有含有過去時間段的連結了,接下來需要分析每一個連結對應的具體網頁的結構,從中獲取天氣資訊。

分析天氣網頁結構

之前的連結http://www.tianqihoubao.com/lishi/beijing.html是一個站點連結,在上節中已經分析了具體的天氣網頁對應的連結集合,如http://www.tianqihoubao.com/lishi/beijing/month/201101.html

現在需要從該頁面中分析出天氣,和解析站點結構中的目標連結一樣,在瀏覽器中觀察Html程式碼,發現天氣這個目標內容在一個表格中,因此我們只需要選出<tr>節點就可以,因為一個<tr>節點表示某一天的天氣(天氣狀況、氣溫和風力方向)。

public static void ParseDailyWeather(string html)
{
    var doc = new HtmlDocument();
    doc.LoadHtml(html);
    var rows = doc.DocumentNode.SelectNodes("//tr");
    StringBuilder sb = new StringBuilder();
    rows.RemoveAt(0);
    foreach (var row in rows)
    {
        var cols = row.SelectNodes("td");
        foreach (var col in cols)
        {
            string temp = col.InnerText.Replace("\r\n", "").Replace(" ", "").Trim();
            sb.Append(temp + ",");
        }
        sb.Append("\r\n");
    }
    FileStream fs = new FileStream("output.csv", FileMode.Append, FileAccess.Write);
    StreamWriter sw = new StreamWriter(fs, Encoding.GetEncoding("gbk"));
    sw.WriteLine(sb);
    sw.Close();
    fs.Close();
}

最後,為了實現站點的爬取,需要一個迴圈來實現所有網頁的爬取

public static void ParseWebsite(string url)
{
    string html = Weather.GetHtml(url);
    var links = Weather.ParseLink(html);
    foreach (var link in links)
    {
        url = "http://www.tianqihoubao.com" + link;
        html = Weather.GetHtml(url);
        Weather.ParseDailyWeather(html);
    }
}

總結

靜態網頁的爬取比較簡單,分為以下幾個步驟就可以

  • 確定內容和站點。
  • 分析站點結構。從站點結構中找出目標連結的特點,分析出所有目標連結。
  • 分析網頁結構。在目標連結的網頁中找出目標內容的特點,提取目標內容。