【问题标题】:c# crawling rule didn't work to cnn web sitec#爬取规则对cnn网站不起作用
【发布时间】:2023-03-03 06:04:23
【问题描述】:

我是 C# 爬虫的初学者

我已尝试从 (https://edition.cnn.com/) 抓取 CNN 头条新闻

但我没有得到标题文本。

target 看起来像下面的html(抱歉我不擅长问包含源代码的问题,新手T.T)

<div class="cd__wrapper" data-analytics="_list-hierarchical-xs_article_">
<div class="cd__content">
<h3 class="cd__headline" data-analytics="_list-hierarchical-xs_article_">
<a href="/travel/article/cruise-ship-passengers-stranded-coronavirus/index.html">
<span class="cd__headline-text">At least 30 cruise ships are at sea. Here's what it's like on board.</span><span class="cd__headline-icon cnn-icon"></span></a></h3></div></div>

首先我尝试爬取所有 html 代码 然后转换为字符串 (我的目标是获取带有用于抓取子页面的href链接的标题文本)

使用以下 c# 代码

public async void GetCnnAsync()
    {
        var url = "https://edition.cnn.com/";

        var httpClient = new HttpClient();
        var html = await httpClient.GetStringAsync(url);

        var htmlDocument = new Hp.HtmlDocument();
        htmlDocument.LoadHtml(html);

        var headLineHtmlList = htmlDocument.DocumentNode.Descendants("div")
            .Where(node => node.GetAttributeValue("class", "")
            .Contains("cd__headline")).ToList();


        Console.ReadLine();
    }

但它没有工作只是得到空 headLineHtmlList 我不知道为什么我没有得到结果。因为 chrome 页面检查器源具有该元素

另一方面,当我尝试将它用于 stackoverflow 站点时。 我能够使用以下代码获得问题列表

public async void GetHtmlAsync()
    {
        var url = "https://stackoverflow.com/questions";

        var httpClient = new HttpClient();
        var html = await httpClient.GetStringAsync(url);

        var htmlDocument = new Hp.HtmlDocument();
        htmlDocument.LoadHtml(html);

        var questionsHtml = htmlDocument.DocumentNode.Descendants("div")
            .Where(node => node.GetAttributeValue("id", "")
            .Equals("questions")).ToList();

        var questionList = questionsHtml[0].Descendants("div")
            .Where(node => node.GetAttributeValue("id", "")
            .Contains("question-summary")).ToList();
    }

可以获取问题列表。

现在我真的很想从 CNN 网站获得结果 请帮我 提前致谢

添加更多测试代码

创建 WebBrowser 控件
然后导航然后获取 WebBrowser_DocumentCompleted 回调

但我没有再次得到结果

所以,我再次尝试使用 documentCompleted 但是没看懂

        WebBrowser webBrowser;
    Control parent;
    WebNewsCallback newsCallback;

    public WebNewsCrawler(Control parent, WebNewsCallback newsCallback) {
        this.parent = parent;
        this.newsCallback = newsCallback;
        if (webBrowser == null) {
            webBrowser = new WebBrowser {
                Visible = false,
                ScriptErrorsSuppressed = true
            };
        }
        parent.Controls.Add(webBrowser);
        webBrowser.DocumentCompleted += WebBrowser_DocumentCompleted;
    }

    public void doWork(string address) {
        webBrowser.Navigate(address);
    }

    int count = 0;

    private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
        if (webBrowser.ReadyState != WebBrowserReadyState.Complete) return;
        newsCallback(webBrowser.DocumentStream);
        GetCnn(webBrowser.DocumentStream);
        Console.WriteLine(count.ToString());
        count++;
    }

    public void GetCnn(Stream stream) {
        var doc = new Hp.HtmlDocument();
        doc.Load(stream, Encoding.UTF8);

        var nodes = doc.DocumentNode.SelectNodes("/html/body/div[7]/section[2]/div[2]/div/div[1]/ul/li[4]/article/div/div/h3/a/span[1]");
        if(nodes != null) {
            Console.WriteLine("xpath nodes not null");
        }

        var headLineHtmlList = doc.DocumentNode.Descendants("h3").ToList();                
        if (headLineHtmlList != null) {
            Console.WriteLine("headLineCount " +headLineHtmlList.Count.ToString());
        }
    }

headLineCount 为 0 且 xPath 结果为零(xpath 或 xpath 完整路径相同的结果)

【问题讨论】:

  • 因为CNN使用JavaScript渲染,可能是React之类的。
  • ... 所以你需要一个无头网络浏览器。 HttpClient() 无法获取完整的动态页面。
  • @Jimi 所以我再次尝试使用无头网络浏览器 if (webBrowser == null) { webBrowser = new WebBrowser { Visible = false, ScriptErrorsSuppressed = true }; } parent.Controls.Add(webBrowser); webBrowser.DocumentCompleted += WebBrowser_DocumentCompleted;但它未能再次得到结果。
  • CompletedEventArgs e) { ThreadPool.QueueUserWorkItem(new WaitCallback(myAsyncOperation)); } void myAsyncOperation(Object state) { Thread.Sleep(5000); if (webBrowser.InvokeRequired) { webBrowser.Invoke(new Action(delegate () { newsCallback(webBrowser.DocumentStream); GetCnn(webBrowser.DocumentStream); })); } } 但我没有得到结果 T.T
  • 删除所有线程相关的东西。另外,您不需要在 UI 中显示控件:您可以初始化一个 headless(无 UI)WebBrowser 类。在DocumentCompleted 处理程序中,检查if ([WebBrowser].ReadyState != WebBrowserReadyState.Complete) return; 等。阅读注释here。请参阅与 HtmlCodument 的 Frames/IFrames 相关的部分。 + 很多例子

标签: c# html parsing web-crawler conv-neural-network


【解决方案1】:

您确定您使用的选择器是正确的吗?你说:

var headLineHtmlList = htmlDocument.DocumentNode.Descendants("div") .Where(node => node.GetAttributeValue("class", "") .Contains("cd__headline")).ToList();

这不是说“给我所有带有标签&lt;div&gt;和一个CSS类cd__headline的后代”吗?

但您不是在寻找具有 cd__headline 类的 div。您正在寻找出现在 &lt;h3&gt; 标签内的 &lt;a&gt; 标签,其 CSS 类为 cd__headline。

我可能是错的,但如果我是对的,那将很容易解决!祝你好运。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-27
    • 1970-01-01
    相关资源
    最近更新 更多