【问题标题】:LINQ Extract data from website using HTMLAgilityPackLINQ 使用 HTMLAgilityPack 从网站中提取数据
【发布时间】:2015-11-15 21:41:51
【问题描述】:

我正在使用 C# HTMLAgilityPack 从中文网站中提取商品名称、价格和货币符号:https://meadjohnson.world.tmall.com/search.htm?search=y&orderType=defaultSort&s‌​cene=taobao_shop。以下是 html 外观的要点:

<div class="SaleItems">
    <dl class="item ">
        <dt class="photo"></dt>
        <dd class="detail">
            <a class="item-name">iPad</a>
            <div class="price-area">
                <span class="symbol">USD</span>
                <span class="price">379</span>
            </div>
        </dd>
    </dl>
    <dl class="item ">
        <dt class="photo"></dt>
        <dd class="detail">
            <a class="item-name">iPod</a>
            <div class="price-area">
                <span class="symbol">CAD</span>
                <span class="price">139</span>
            </div>
        </dd>
    </dl>
</div>

到目前为止,这就是我的程序的样子。

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
    | SecurityProtocolType.Tls11
    | SecurityProtocolType.Tls12
    | SecurityProtocolType.Ssl3;

var htmlDocument = htmlWeb.Load(html);
var sItems = doc.DocumentNode.Descendants("SaleItems"); 
foreach (var item in sItems)
{
  var data = new {
         Currency  = item["symbol"].InnerText,
         Price = item["price"].InnerText,
         };
}

这不起作用。我该如何解决我做错的事情?

【问题讨论】:

  • 你现在所做的事情到底有什么不妥?
  • 我收到错误“无法使用 [] 将索引应用于 'HtmlAgilityPack.HtmlNode' 类型的表达式”

标签: linq c#-4.0 html-agility-pack data-extraction


【解决方案1】:

您可以通过这种方式提取数据:

var input = @"<div class='SaleItems'>
    <dl class='item '>
        <dt class='photo'></dt>
        <dd class='detail'>
            <a class='item-name'>iPad</a>
            <div class='price-area'>
                <span class='symbol'>USD</span>
                <span class='price'>379</span>
            </div>
        </dd>
    </dl>
    <dl class='item '>
        <dt class='photo'></dt>
        <dd class='detail'>
            <a class='item-name'>iPod</a>
            <div class='price-area'>
                <span class='symbol'>CAD</span>
                <span class='price'>139</span>
            </div>
        </dd>
    </dl>
</div>";
var html = new HtmlDocument();
html.LoadHtml(input);
var root = html.DocumentNode;
var list = new List<Data>();
foreach (var node in root.Descendants("dl"))
{
    var currency = node.Descendants()
       .Where(n => n.GetAttributeValue("class", "").Equals("symbol")).FirstOrDefault().InnerText;
    var price = node.Descendants()
       .Where(n => n.GetAttributeValue("class", "").Equals("price")).FirstOrDefault().InnerText;
    list.Add(new Data { Currency = currency, Price = price});
}

public class Data
{
    public string Currency { get; set; }
    public string Price { get; set; }
}

或者您可以使用query expression 代替foreach 部分:

var list = (from node in root.Descendants("dl") 
            let currency = node.Descendants().Where(n => n.GetAttributeValue("class", "").Equals("symbol")).FirstOrDefault().InnerText 
            let price = node.Descendants().Where(n => n.GetAttributeValue("class", "").Equals("price")).FirstOrDefault().InnerText 
            select new Data {Currency = currency, Price = price}).ToList();

【讨论】:

  • 这不起作用。该程序不喜欢root.Descendants("dl")
  • @inquisitive_one rootdoc.DocumentNode.root
  • 我将foreach stmt 更改为foreach (var node in html.DocumentNode.Descendants("dl")) {。它仍然不起作用。还有什么我需要改变的吗?
  • @inquisitive_one 有什么错误?该代码在我的计算机上没有任何问题。另一件事 input 包含您的 HTML 作为字符串
  • 这很奇怪。我没有收到错误。我没有进入foreach 循环。是的,我使用的inputhttps://meadjohnson.world.tmall.com/search.htm?search=y&amp;orderType=defaultSort&amp;scene=taobao_shop。我不确定你的代码为什么不喜欢那个网站。
【解决方案2】:

确切的错误是,在 foreach() 块中,“item”是 HtmlNode 类型的变量,但您正在尝试“索引”它。而不是这个,你应该使用

item.Descendants("symbol") 

item.SelectSingleNode(".//span[@class='symbol']");

或者您可以使用以下代码:

    var document = new HtmlWeb();
    var root = document.Load(url);
    var data = new List<Item>();
    foreach (var item in root.DocumentNode.SelectNodes("//dl"){
        var name = item.SelectSingleNode(".//a[@class='item-name']").InnerText;
        var price = item.SelectSingleNode(".//span[@class='price']").InnerText;
        var symbol = item.SelectSingleNode(".//span[@class='symbol']").InnerText;
        data.Add(new Item(){ Name = name, Price = price, Symbol = symbol });
    }
    public class Item{
        public string Name;
        public int Price;
        public string Symbol;
    }

【讨论】:

  • 现在,我收到“NullReferenceException:对象引用未设置为对象实例”。我将查询更改为:var name = item.SelectSingleNode(".//a[@class='item-name']").InnerText == null ? String.Empty : item.SelectSingleNode(".//a[@class='item-name']").InnerText; 这也不起作用。我现在该怎么办?
  • 我可以使用任何其他想法吗?
  • 你到底在哪里得到异常?
  • 注意:我使用的网站是https://meadjohnson.world.tmall.com/search.htm?search=y&amp;orderType=defaultSort&amp;scene=taobao_shop。我在var name = item.SelectSingleNode(".//a[@class='item-name']").InnerText; 上收到上述错误。
  • 查看foreach块中的“item”变量是否不为空,然后说明页面中是否真的存在该类名的item。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-18
  • 2020-11-24
  • 1970-01-01
  • 2020-03-03
  • 2012-12-21
  • 2017-01-23
  • 1970-01-01
相关资源
最近更新 更多