Nhận mã HTML từ trang web trong C #


87

Làm cách nào để lấy mã HTML từ một trang web, lưu nó và tìm một số văn bản bằng biểu thức LINQ?

Tôi đang sử dụng mã sau để lấy nguồn của một trang web:

public static String code(string Url)
{
    HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(Url);
    myRequest.Method = "GET";
    WebResponse myResponse = myRequest.GetResponse();
    StreamReader sr = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);
    string result = sr.ReadToEnd();
    sr.Close();
    myResponse.Close();

    return result;
 }

Làm cách nào để tìm văn bản trong div trong nguồn của trang web?


Phụ thuộc vào cách tìm kiếm thông minh. Một Containscuộc gọi đơn giản có thể là "đủ tốt".
ashes999

5
Hãy xem xét việc sử dụng HTMLAgility pack, Fizzler hoặc CSQuery để lấy div / text khi bạn có HTML, bất kỳ thứ gì khác đều quá dễ xảy ra lỗi.
jammykam


@GeorgeDuckett Có vẻ như câu hỏi này không trùng lặp với câu hỏi này, câu hỏi mà bạn liên kết đến chỉ là về truy xuất nguồn, câu hỏi này cũng là về truy vấn DOM.
Mark Rotteveel

@Mark: Xin lỗi bạn nói khá đúng, đã bỏ sót dòng chữ ở dưới cùng.
George Duckett

Câu trả lời:


112

Lấy mã HTML từ một trang web. Bạn có thể sử dụng mã như thế này.

string urlAddress = "http://google.com";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlAddress);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

if (response.StatusCode == HttpStatusCode.OK)
{
  Stream receiveStream = response.GetResponseStream();
  StreamReader readStream = null;

  if (String.IsNullOrWhiteSpace(response.CharacterSet))
     readStream = new StreamReader(receiveStream);
  else
     readStream = new StreamReader(receiveStream, Encoding.GetEncoding(response.CharacterSet));

  string data = readStream.ReadToEnd();

  response.Close();
  readStream.Close();
}

Điều này sẽ cung cấp cho bạn mã HTML được trả về từ trang web. Nhưng tìm văn bản qua LINQ không phải là dễ dàng. Có lẽ tốt hơn là sử dụng biểu thức chính quy nhưng điều đó không phù hợp với mã HTML


4
Ý tưởng sử dụng regex cho html hoặc XML là thực hành mã hóa RẤT tồi tệ ... Đi theo cách của bạn - chúng ta nên sử dụng từ khóa goto ở mọi nơi ...
Lightning 3

Trên thực tế, sử dụng regex để tìm kiếm một thứ chính xác trong mã HTML có thể là một giải pháp rất tốt. Mặt khác, cố gắng xây dựng một trình phân tích cú pháp / trình thông dịch HTML dựa trên regex sẽ là một sự điên rồ. Tất cả phụ thuộc vào ngữ cảnh và nhiệm vụ thực tế cần được thực hiện, nhưng nói rằng "regex không bao giờ chơi tốt với HTML" đơn giản không phải là một sự thật toàn cầu, không thể giải thích được. stackoverflow.com/a/1733489/6838730
Mathieu VIALES

177

Tốt hơn, bạn có thể sử dụng lớp Webclient để đơn giản hóa tác vụ của mình:

using System.Net;

using (WebClient client = new WebClient())
{
    string htmlCode = client.DownloadString("http://somesite.com/default.html");
}

Bất kỳ ý tưởng tại sao tôi gặp lỗi này? 'System.Net.WebClient': loại sử dụng trong một tuyên bố sử dụng phải được ngầm chuyển đổi thành 'System.IDisposable'
Dave Chandler

9
Đối với các usingyêu cầu chứng minh rõ ràng cho mọi người sử dụng: 1
user3916429

37

Điều tốt nhất để sử dụng là HTMLAgilityPack . Bạn cũng có thể xem xét sử dụng Fizzler hoặc CSQuery tùy thuộc vào nhu cầu của bạn để chọn các phần tử từ trang được truy xuất. Sử dụng Biểu thức LINQ hoặc Regukar dễ xảy ra lỗi, đặc biệt khi HTML có thể bị sai định dạng, thiếu thẻ đóng, có các phần tử con lồng nhau, v.v.

Bạn cần truyền trang vào một đối tượng HtmlDocument và sau đó chọn phần tử bạn yêu cầu.

// Call the page and get the generated HTML
var doc = new HtmlAgilityPack.HtmlDocument();
HtmlAgilityPack.HtmlNode.ElementsFlags["br"] = HtmlAgilityPack.HtmlElementFlag.Empty;
doc.OptionWriteEmptyNodes = true;

try
{
    var webRequest = HttpWebRequest.Create(pageUrl);
    Stream stream = webRequest.GetResponse().GetResponseStream();
    doc.Load(stream);
    stream.Close();
}
catch (System.UriFormatException uex)
{
    Log.Fatal("There was an error in the format of the url: " + itemUrl, uex);
    throw;
}
catch (System.Net.WebException wex)
{
    Log.Fatal("There was an error connecting to the url: " + itemUrl, wex);
    throw;
}

//get the div by id and then get the inner text 
string testDivSelector = "//div[@id='test']";
var divString = doc.DocumentNode.SelectSingleNode(testDivSelector).InnerHtml.ToString();

[EDIT] Trên thực tế, bỏ qua. Phương pháp đơn giản nhất là sử dụng FizzlerEx , một triển khai jQuery / CSS3-selectors được cập nhật của dự án Fizzler ban đầu.

Mẫu mã trực tiếp từ trang web của họ:

using HtmlAgilityPack;
using Fizzler.Systems.HtmlAgilityPack;

//get the page
var web = new HtmlWeb();
var document = web.Load("http://example.com/page.html");
var page = document.DocumentNode;

//loop through all div tags with item css class
foreach(var item in page.QuerySelectorAll("div.item"))
{
    var title = item.QuerySelector("h3:not(.share)").InnerText;
    var date = DateTime.Parse(item.QuerySelector("span:eq(2)").InnerText);
    var description = item.QuerySelector("span:has(b)").InnerHtml;
}

Tôi không nghĩ nó có thể trở nên đơn giản hơn thế.


Điều gì xảy ra nếu tôi muốn gọi một nút cụ thể trên trang web? @jammykam
Jamshaid Kamran

1
Bạn không thể làm điều đó với máy quét màn hình afaik, bạn sẽ phải sử dụng bất kỳ thứ gì như Selenium để gọi nút.
jammykam

Bạn cài đặt FizzlerEx như thế nào? Tôi kiểm tra liên kết và có một .zip nhưng không thấy bất kỳ cài đặt
Juan Carlos Oropeza

5

Tôi đang sử dụng AngleSharp và rất hài lòng với nó.

Đây là một ví dụ đơn giản về cách tìm nạp một trang:

var config = Configuration.Default.WithDefaultLoader();
var document = await BrowsingContext.New(config).OpenAsync("https://www.google.com");

Và bây giờ bạn có một trang web trong biến tài liệu . Sau đó, bạn có thể dễ dàng truy cập nó bằng LINQ hoặc các phương pháp khác. Ví dụ: nếu bạn muốn lấy giá trị chuỗi từ bảng HTML:

var someStringValue = document.All.Where(m =>
        m.LocalName == "td" &&
        m.HasAttribute("class") &&
        m.GetAttribute("class").Contains("pid-1-bid")
    ).ElementAt(0).TextContent.ToString();

Để sử dụng bộ chọn CSS, vui lòng xem các ví dụ về AngleSharp .


5

Đây là một ví dụ về việc sử dụng HttpWebRequestlớp để tìm nạp một URL

private void buttonl_Click(object sender, EventArgs e) 
{ 
    String url = TextBox_url.Text;
    HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); 
    HttpWebResponse response = (HttpWebResponse) request.GetResponse(); 
    StreamReader sr = new StreamReader(response.GetResponseStream()); 
    richTextBox1.Text = sr.ReadToEnd(); 
    sr.Close(); 
} 

2
bạn nên thêm mã vào câu trả lời của mình thay vì một hình ảnh.
AJ

2

Bạn có thể sử dụng WebClient để tải xuống html cho bất kỳ url nào. Khi bạn có html, bạn có thể sử dụng thư viện của bên thứ ba như HtmlAgilityPack để tra cứu các giá trị trong html như trong mã bên dưới:

public static string GetInnerHtmlFromDiv(string url)
    {
        string HTML;
        using (var wc = new WebClient())
        {
            HTML = wc.DownloadString(url);
        }
        var doc = new HtmlAgilityPack.HtmlDocument();
        doc.LoadHtml(HTML);
        
        HtmlNode element = doc.DocumentNode.SelectSingleNode("//div[@id='<div id here>']");
        if (element != null)
        {
            return element.InnerHtml.ToString();
        }   
        return null;            
    }

1

Hãy thử giải pháp này. Nó hoạt động tốt.

 try{
        String url = textBox1.Text;
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        StreamReader sr = new StreamReader(response.GetResponseStream());
        HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
        doc.Load(sr);
        var aTags = doc.DocumentNode.SelectNodes("//a");
        int counter = 1;
        if (aTags != null)
        {
            foreach (var aTag in aTags)
            {
                richTextBox1.Text +=  aTag.InnerHtml +  "\n" ;
                counter++;
            }
        }
        sr.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Failed to retrieve related keywords." + ex);
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.