รับโค้ด HTML จากเว็บไซต์ใน C #


89

วิธีรับโค้ด HTML จากเว็บไซต์บันทึกและค้นหาข้อความโดยใช้นิพจน์ LINQ

ฉันใช้รหัสต่อไปนี้เพื่อรับแหล่งที่มาของหน้าเว็บ:

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;
 }

ฉันจะค้นหาข้อความใน div ในแหล่งที่มาของหน้าเว็บได้อย่างไร


ขึ้นอยู่กับว่าการค้นหาที่ชาญฉลาดควรเป็นอย่างไร คำContainsเรียกง่ายๆอาจจะ "ดีพอ"
ashes999

5
พิจารณาการใช้ HTMLAgility pack, Fizzler หรือ CSQuery เพื่อรับ div / text เมื่อคุณมี HTML แล้วสิ่งอื่น ๆ ก็มักจะเกิดข้อผิดพลาดเช่นกัน
jammykam


@GeorgeDuckett ดูเหมือนคำถามนี้จะไม่ซ้ำกันคำถามที่คุณเชื่อมโยงเป็นเพียงการดึงแหล่งที่มาเท่านั้นคำถามนี้เกี่ยวกับการสืบค้น DOM ด้วย
Mark Rotteveel

@ มาร์ค: ขออภัยคุณพูดถูกผิดพลาดข้อความด้านล่าง
George Duckett

คำตอบ:


113

รับโค้ด HTML จากเว็บไซต์ คุณสามารถใช้รหัสเช่นนี้

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();
}

สิ่งนี้จะให้โค้ด HTML ที่ส่งคืนจากเว็บไซต์ แต่การค้นหาข้อความผ่านLINQนั้นไม่ใช่เรื่องง่าย บางทีมันอาจจะดีกว่าที่จะใช้การแสดงออกปกติ แต่ไม่ได้เล่นได้ดีกับHTMLรหัส


4
แนวคิดในการใช้ regex สำหรับ html หรือ XML เป็นการฝึกฝนการเขียนโค้ดที่ไม่ดีมาก ... ไปในทางของคุณ - เราควรใช้คีย์เวิร์ด goto ทุกที่ ...
Lightning3

1
จริงๆแล้วการใช้ regex เพื่อค้นหาสิ่งที่แม่นยำภายในโค้ด HTML อาจเป็นวิธีแก้ปัญหาที่ดีมาก ในทางกลับกันการพยายามสร้างตัวแยกวิเคราะห์ / ตัวแปล HTML ตาม regex จะเป็นความบ้าคลั่งอย่างแท้จริง ทุกอย่างขึ้นอยู่กับบริบทและงานจริงที่ต้องดำเนินการ แต่การบอกว่า "regex ไม่เคยเล่นกับ HTML ได้ดี" ไม่ใช่ความจริงระดับโลกที่ไม่สามารถเปลี่ยนแปลงได้ stackoverflow.com/a/1733489/6838730
Mathieu VIALES

183

ดีกว่าคุณสามารถใช้คลาส Webclient เพื่อทำให้งานของคุณง่ายขึ้น:

using System.Net;

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

มีความคิดว่าทำไมฉันจึงได้รับข้อผิดพลาดนี้ 'System.Net.WebClient': ประเภทที่ใช้ในคำสั่งใช้จะต้องแปลงเป็น 'System.IDisposable' โดยปริยาย
Dave Chandler

10
สำหรับusingข้อกำหนดที่แสดงให้ทุกคนใช้อย่างชัดเจน: +1
user3916429

สำหรับผู้ที่ได้รับข้อผิดพลาด http 403 ให้เพิ่ม client.Headers.Add ("user-agent", "Fiddler"); แทนที่ Fiddler ด้วยข้อความที่คุณต้องการ
Himanshu Patel

37

สิ่งที่ดีที่สุดที่จะใช้เป็นHTMLAgilityPack คุณยังสามารถดูโดยใช้FizzlerหรือCSQuery ได้ขึ้นอยู่กับความต้องการของคุณในการเลือกองค์ประกอบจากหน้าที่ดึงข้อมูล การใช้ LINQ หรือ Regukar Expressions เป็นเพียงการเกิดข้อผิดพลาดโดยเฉพาะอย่างยิ่งเมื่อ HTML มีรูปแบบไม่ถูกต้องไม่มีแท็กปิดมีองค์ประกอบย่อยซ้อนกันเป็นต้น

คุณต้องสตรีมเพจไปยังอ็อบเจ็กต์ HtmlDocument จากนั้นเลือกองค์ประกอบที่คุณต้องการ

// 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();

[แก้ไข] ที่จริงเรื่องที่สนใจ วิธีที่ง่ายที่สุดคือใช้FizzlerExซึ่งเป็น jQuery / CSS3-selectors ที่ปรับปรุงแล้วของโครงการ Fizzler ดั้งเดิม

ตัวอย่างโค้ดโดยตรงจากไซต์ของพวกเขา:

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;
}

ฉันไม่คิดว่ามันจะง่ายไปกว่านั้น


จะเกิดอะไรขึ้นถ้าฉันต้องการเรียกใช้ปุ่มเฉพาะบนหน้าเว็บ? @jammykam
Jamshaid K.

1
คุณไม่สามารถทำได้ด้วยมีดโกนหน้าจอ afaik คุณจะต้องใช้อะไรอย่างเช่น Selenium เพื่อเรียกใช้ปุ่ม
jammykam

คุณติดตั้ง FizzlerEx ได้อย่างไร? ฉันตรวจสอบลิงค์และมี. zip แต่ไม่เห็นตัวติดตั้งใด ๆ
Juan Carlos Oropeza

6

ฉันใช้AngleSharpและพอใจกับมันมาก

นี่คือตัวอย่างง่ายๆในการดึงข้อมูลเพจ:

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

และตอนนี้คุณมีหน้าเว็บในตัวแปรเอกสาร จากนั้นคุณสามารถเข้าถึงได้อย่างง่ายดายโดย LINQ หรือวิธีการอื่น ๆ ตัวอย่างเช่นหากคุณต้องการรับค่าสตริงจากตาราง HTML:

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

หากต้องการใช้ตัวเลือก CSS โปรดดูตัวอย่าง AngleSharp


5

นี่คือตัวอย่างของการใช้HttpWebRequestคลาสเพื่อดึง 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
คุณควรเพิ่มรหัสในคำตอบของคุณแทนรูปภาพ
AJ

2

คุณสามารถใช้ WebClient เพื่อดาวน์โหลด html สำหรับ url ใดก็ได้ เมื่อคุณมี html แล้วคุณสามารถใช้ไลบรารีของบุคคลที่สามเช่นHtmlAgilityPackเพื่อค้นหาค่าใน html ตามโค้ดด้านล่าง -

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

ลองใช้วิธีนี้ มันทำงานได้ดี

 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);
        }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.