我试图从下面提到的网站中提取价格。我使用AngleSharp进行提取。在网站上,价格如下(例如):
<span class="c-price">650.00 </span>
我使用以下代码进行提取。
using AngleSharp.Parser.Html;
using System.Net;
using System.Net.Http
//Make the request
var uri = "https://meadjohnson.world.tmall.com/search.htm?search=y&orderType=defaultSort&scene=taobao_shop";
var cancellationToken = new CancellationTokenSource();
var httpClient = new HttpClient();
var request = await httpClient.GetAsync(uri);
cancellationToken.Token.ThrowIfCancellationRequested();
//Get the response stream
var response = await request.Content.ReadAsStreamAsync();
cancellationToken.Token.ThrowIfCancellationRequested();
//Parse the stream
var parser = new HtmlParser();
var document = parser.Parse(response);
//Do something with LINQ
var pricesListItemsLinq = document.All
.Where(m => m.LocalName == "span" && m.ClassList.Equals("c-price"));
Console.WriteLine(pricesListItemsLinq.Count());
但是,我没有收到任何物品,但他们在网站上。我究竟做错了什么?如果AngleSharp不是推荐的方法,我应该使用什么?我应该使用什么代码?
答案 0 :(得分:4)
我在聚会上迟到了,但我试着在这里带来一些理智。
为此,我们需要以下一套工具/功能:
AngleSharp为我们提供了所有这些选项(减去与证书存储/已知CA的连接;因此,为了使用HTTPS,我们必须进行一些额外的配置,例如,接受所有证书)。
我们首先创建一个AngleSharp配置,定义哪些功能可用于浏览引擎。该引擎以“浏览上下文”的形式公开,可以将其视为无头标签。在此选项卡中,我们可以打开一个新文档(来自本地源,构造源或远程源)。
var config = Configuration.Default.WithDefaultLoader();
var context = BrowsingContext.New(config);
var document = await context.OpenAsync("http://example.com");
一旦我们有了文档,我们就可以使用CSS查询选择器来获取某些元素。这些元素可用于收集我们要查找的信息。
AngleSharp包含LINQ(或一般IEnumerable),但是,如果可能的话,为查询提供全部功能是有意义的。
所以而不是
var pricesListItemsLinq = document.All
.Where(m => m.LocalName == "span" && m.ClassList.Equals("c-price"));
我们写
var pricesListItemsLinq = document.QuerySelectorAll("span.c-price");
这也更加健壮(ClassList
无论如何都是一个复杂的对象,可以访问类列表,所以你要么意味着ClassList.Contains
,要么ClassName.Equals
(后者是字符串)注意:两个版本不等价,因为前者在类列表中寻找一个类,而后者正在寻找整个类序列化的匹配(从而在匹配上构成一些额外的边界条件;它需要是唯一的一个类。)
这要复杂得多。基础知识与以前相同,但引擎需要提供的不仅仅是前面提到的要求。另外,我们需要
虽然有一个项目向AngleSharp提供实验(且有限)仅限C#的JS引擎,但后两个要求目前无法完全实现。此外,CSSOM对于一个或另一个Web应用程序也可能不够完整。请记住,这些页面可能是为真正的浏览器设计的。他们做出某些假设。他们甚至可能需要用户输入(例如,Google Captcha)。
长话短说。
var config = Configuration.Default
.WithDefaultLoader()
.WithCss()
.WithJavaScript(); // maybe even more
var context = BrowsingContext.New(config);
打开新文档时await
后面的任务等同于DOM中的load
事件。因此,在下载和解析文档时不会触发,但只有在加载(并且可能运行)所有脚本时才会触发。需要下载的资源。
希望这有点帮助!