【发布时间】: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