Trang chủ » CSharp » Sử dụng thư viện HtmlAgilityPack để xử lý văn bản html

Sử dụng thư viện HtmlAgilityPack để xử lý văn bản html


Việc xử  lý văn bản html và trích xuất các phần tử  dom trong văn bản html thường gây cho LTV chúng ta gặp nhiều khó khăn, một giải pháp mà người ta hay dùng là dùng regex để tách các đoạn các thẻ trong văn bản html, nay chúng ta có thể sử  dụng thư  viện HtmlAgilityPack và dùng LINQ để truy vấn sẽ đơn giản hơn nhiều

Đầu tiên download thư  viện : HtmlAgilityPack tại đây

vào visual studio add file HtmlAgilityPack.dll vào Refercences

Ví dụ :

Đầu tiên tạo 1 request đến trang http://dantri.com.vn

string root = “http://dantri.com.vn”;
WebRequest request = WebRequest.Create(root);
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
var dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();

Sau khi thực hiện lệnh này mã html sẽ nằm ở biến responseFromServer chúng ta bắt đầu xử  lý sử  dụng thư  viện trên

Lấy tất cả link có trong trang :

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(responseFromServer);

List<HtmlNode> links = (from node in doc.DocumentNode.SelectNodes(“//a[@href]”).Cast<HtmlNode>()
where ((node.Attributes[“href”].Value.StartsWith(“/”)) & (node.Attributes[“href”].Value.EndsWith(“.htm”)))
select node).ToList<HtmlNode>();

Lấy tất cả thẻ div có class là : fon31 mt1

 var title = (from m in doc.DocumentNode.SelectNodes(“//div[@class]”).Cast<HtmlNode>()
where m.Attributes[“class”].Value == “fon31 mt1”
select m).ToList<HtmlNode>();

….

Để lấy được nội dung của đoạn text ta sử  dụng thuộc tính InnerHtml trong class HtmlNode 😀

Để xử  lý các truy vấn khác các bạn cần biết đến Xpath

Vậy ứng dụng của việc này để làm gì?

– Các bạn có thể một tool lấy tin tự  động từ  dân trí hay các trang khác ^_^!

– Sử  dụng để viết Web crawler 🙂

Nhận xét :

Có nhiều cách để làm được việc cần nói ở trên nhưng các này đơn giản và viết ngắn gọn hơn ^_^!

Advertisements

37 thoughts on “Sử dụng thư viện HtmlAgilityPack để xử lý văn bản html

    • Nếu bạn muốn in cái list links ở trên, bạn phải cho vòng lặp:
      foreach (HtmlNode link in links)
      {
      MessageBox.Show(link.Attributes[“href”].Value);
      }
      thì mới lấy được nha.
      Chúc thành công!

  1. (from node in doc.DocumentNode.SelectNodes(“//a[@href]”).Cast()
    where((node.Attributes[“href”].Value.StartsWith(“/”))
    (node.Attributes[“href”].Value.EndsWith(“.htm”)))
    select node).ToList();
    sao đoạn này của mình báo “Method name expected”?

  2. – các bạn ơi cho mình hỏi xíu, mình không thể lấy được nội dung trong xpath, muốn lấy thì chỉnh code lại làm sao?
    – dưới đây là code của mình, nó ko lấy được nội dung trong xpath.

    var content_tag_div = from content in htDoc.DocumentNode.SelectNodes(“//div[@class]”)
    where content.Attributes[“class”].Value == “tool_all”
    select new
    {
    tieude=content.SelectNodes(“/html/body/div/div[4]/div/div/div[2]/h3”)
    };
    foreach (var c in content_tag_div)
    {
    richTextBox1.Text = c.tieude.tostring();
    }

  3. var content_tag_div = from content in htDoc.DocumentNode.SelectNodes(“//div[@class]“)
    where content.Attributes[“class”].Value == “tool_all”
    Theo minh ban nen sua thanh
    var content_tag_div = from content in htDoc.DocumentNode.SelectNodes(“//div[@class=’tool_all’]“)
    thi chinh sac hon.Mình mới học nên chỉ biết vậy thui.Nếu có hứng thú gửi mail anh em mình cùng chia sẻ thêm

  4. where content.Attributes[“class”].Value == “tool_all”=false;
    Cái câu lệnh Attributes có nghĩa là có lấy ra thuộc tính.Nhưng class thì không phải là thuộc tính mà nó chỉ là tên thuộc tính thôi

  5. Mình muốn hỏi bạn một vấn đề, nếu bạn có thể giúp đc mình thì gửi cho mình yahoo hoặc số điện thoại mình hỏi cụ thể:

    vấn đề của mình như sau: mình viết 1 phần mềm tự động download công văn từ trang ninhbinh.edu.vn, ngày trước phần mềm hoạt động rất tốt, rồi trang chủ nâng cấp và phần mềm của mình không thể lấy link download đc nữa, mình vào trang web bằng mã
    string txt=””;
    WebRequest request = WebRequest.Create(url);
    WebResponse response = request.GetResponse();
    // Get the stream containing content returned by the server.
    var dataStream = response.GetResponseStream();
    // Open the stream using a StreamReader for easy access.
    StreamReader reader = new StreamReader(dataStream);
    // Read the content.
    string responseFromServer = reader.ReadToEnd();
    // Clean up the streams.
    reader.Close();
    dataStream.Close();
    response.Close();

    responseFromServer ko trả về chuỗi nào có chưa link download
    mình vào = ie sau đó vào view rồi chọn view source thì thấy link để down, bạn có thể giúp mình vấn đề này ko

  6. Mình đã lấy được nội dung của viết, tuy nhiên trong bài viết trên báo của họ lại có ảnh mà link ảnh đó lại là của họ, mình muốn lấy ảnh đó về thì làm sao lấy được thẻ img đó nhỉ

    • Bạn lấy giá trị của nó nằm trong thẻ a thuộc tính href sau đó tiến hành download file ảnh về, hoặc làm tương tự
      node.Attributes(“href”).value thì sẽ lấy được URL của ảnh, sau đó tùy thuộc vào link ảnh như thế nào rồi mình add thêm cái root cho nó nữa hoặc download ảnh về máy mình luôn

  7. mình đang có 1 biến htmlnode chứa nội dung của phần nội dung bài viết, giờ mình không biết là làm sao để tìm dược cái thẻ img đó, còn cách lưu ảnh về máy thì mình biết làm rồi. bạn chỉ cho mình cách tìm thẻ img trong cái biến htmlnode kia được không

    • bạn có thể lấy htmlnode.innertext đó để ra 1 text html chứa nội dung bài viết đó
      sau đó bạn tiếp tục dùng thư viện HtmlAgilityPack và phân tích tiếp nội dung kia và sau đó tiến hành lấy các thẻ image và sau đó lấy thuộc tính src của link ảnh mà bạn vừa tạo

      • mình dùng 1 biến string strbaiviet = htmlnode.innerhtml; nhưng lại gặp khó khăn ở chỗ, kiểu string thì ko biết áp dụng HtmlAgilityPack như thế nào nữa. vì lớp string ko có các hàm như .selectnode,… bạn có thể hướng dẫn mình cụ thể ko

      • Bạn new một đối tượng HtmlDocument ra sau đó load html là đoạn text vừa rồi là được

        HtmlDocument doc = New HtmlDocument()
        doc.LoadHtml(strbaiviet )

        Sau đó bạn dùng xpath để select trong đối tượng doc này

  8. mình đang gặp 1 vấn đề nữa: giả sử biến htmlNode có thuộc tính htmlNode.innerhtml như thế này:
    ….
    ….

    giờ mình muốn là thay đổi cái link kia thành chuuooix của mình

  9. ơ, k hiển thị được đoạn html kia à, đoạn html kia là
    thẻ p… thẻ p
    thẻ p… thẻ a…thẻ img có src=”link”

    • mình làm theo cách b hướng dẫn:
      HtmlDocument baiviet = new HtmlDocument();
      baiviet.LoadHtml(Htmlnode.InnerHtml);
      noc = baiviet.DocumentNode.SelectNodes(“//img”);
      như này thì cái biến noc của mình đã chứ được tất cả các thẻ img và có thể dễ dàng lấy được thuộc tính src, việc tiếp theo là phải thay đổi thuộc tính src này thành 1 đường dẫn trên máy mình. tuy nhiên nếu duyệt từng item trong noc và thay đổi thì nó chỉ thay đổi trong noc, cái mình muốn là thay đổi trong baiviet cơ

      • Chào bạn, mình đã test thử, bạn cứ duyệt vòng for rồi set giá trị cho Attributes rồi gán giá trị bạn cần điền vào là được
        ví dụ nhé
        var node = (From n In doc.DocumentNode.SelectNodes(“//a[@href]”))
        For Each no In node
        no.Attributes(“href”).Value = “https://tranphuochung.wordpress.com/”
        Next
        doc.DocumentNode.InnerHtml ==> giá trị này sẽ thay thế toàn bộ link thành link trên

        Cái này mình viết bằng VB.net bạn chuyển 1 tí là thành ngôn ngữ C# sau đó sử dụng bình thường ah

  10. HtmlDocument baiviet = new HtmlDocument();
    baiviet.LoadHtml(Htmlnode.InnerHtml);
    foreach (HtmlNode Nd in baiviet.DocumentNode.SelectNodes(“//img”))
    {
    HtmlAttribute att = Nd.Attributes[“src”];
    att.Value = “link cua toi”;
    Nd.Attributes[“src”].Value = att.Value;
    }

  11. À được rồi, nãy mình debug xem thuộc tính text của baiviet thì thấy giữ nguyên, gán nó sang biến string thì lại thấy được rồi. thanks b nhiều vì trả lời những câu hỏi của mình 🙂

  12. Ad ơi, cho mình hỏi, mình tổng hợp tin từ 2 trang báo điện tử, nhưng có 1 vấn đề là làm sao để nhận biết tin nào là tin mới để đăng, mình đang làm là so sánh link của những tin quét được với các tin đã lấy trong databse nhưng làm thế có vẻ ko ổn vì databse sẽ ngày càng nhiều tin mà so sánh thế thì sẽ chạy chậm

Bình luận

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s