HtmlAgilityPack - 结果很混乱

问题描述 投票:0回答:1

因此,我想创建一个应用程序,定期从用户提供的产品销售页面获取 HTML。 问题是我不知道如何检索这些值,以免它们混淆。

您可以在图片上看到广告标题与网址不匹配(标题为 iPhone 13,网址为 iPhone 5s):

Title doesn't match with ad URL

var url = url_textbox.Text;
var web = new HtmlWeb();
var doc = web.Load(url);

var allTitles = doc.DocumentNode.SelectNodes("//*[@class='" + adTitleClassName + "']"); // exam: adTitleClassName = css-1wxaaza
var allPrices = doc.DocumentNode.SelectNodes("//*[@class='" + adPriceClassName + "']");
var allLinks = doc.DocumentNode.SelectNodes("//*[@class='" + adLinkClassName + "']");
var allDamaged = doc.DocumentNode.SelectNodes("//*[@class='" + adDamagedClassName + "']");
var allLocations = doc.DocumentNode.SelectNodes("//*[@class='" + adLocationClassName + "']");
var allImages = doc.DocumentNode.SelectNodes("//div[@class='css-gl6djm']");

for (int i = 0; i < allTitles.Count; i++)
{
    var title = allTitles[i].InnerText;
    var price = allPrices[i].InnerText;
    var link = allLinks[i].Attributes["href"].Value;
    var damaged = allDamaged[i].InnerText;
    var timeAdded = allLocations[i].InnerText;
    var imageUrl = allImages[i].SelectNodes("//img/@src")[i].Attributes["src"].Value;
    var negotiate = false;

    var damagedParsed = false;
    if (damaged == "Uszkodzone") damagedParsed = true;

    Ad ad = new Ad();
    ad.Title = title;
    ad.Price = double.Parse(price.Replace("do negocjacji", "").Replace(" zł", "").Replace(" ", ""));
    ad.URL = "https://www.olx.pl" + link;
    ad.Damaged = damagedParsed;
    ad.TimeAdded = timeAdded;
    ad.ImageURL = imageUrl;
    ad.Negotiate = price.Contains("do negocjacji");

    if (only_iphone_checkBox.Checked)
    {
        if (ad.Title.ToLower().Contains("iphone") ||
            ad.Title.ToLower().Contains("apple")) ads.Add(ad);
    } else
    {
        ads.Add(ad);
    }
}

foreach (Ad ad in ads)
{
    AdItem adItem = new AdItem(ad);
    ads_list.Controls.Add(adItem);
}

所以,我认为这是因为它试图单独获取所有信息并将其打包到不同的列表中,从而使信息混淆。

因此,我尝试将页面上显示的待售商品的每张卡片分别收集信息,并使用以下代码:

var url = url_textbox.Text;
var web = new HtmlWeb();
var doc = web.Load(url);

var mainCard = doc.DocumentNode.SelectNodes("//div[@id='AdCardId']");
for (int i = 0; i < mainCard.Count; i++)
{
    var title = mainCard[i].SelectSingleNode("//*[@class='" + adTitleClassName + "']").InnerText;
    Print(title); // It prints always the same title
}

上面代码的结果:

the code above always returns the same text

所以,这对我来说真的没有意义 - 为什么“SelectNodes”方法并不像方法名称所说的那样真正“选择”?

我认为

var title = mainCard[i].SelectSingleNode("//*[@class='" + adTitleClassName + "']").InnerText;

试图在整个 HTML 页面中查找 adTitleClassName 而不是我选择的节点,这就是为什么我为每个产品获得相同的标题。 我如何才能只获取带有代表 AD 的卡片的节点,而不是整个 HTML?

c# html winforms web-scraping
1个回答
0
投票

已修复!

我不知道“SelectSingleNode”方法中可以使用多个表达式。

var url = url_textbox.Text;
var web = new HtmlWeb();
var doc = web.Load(url);

var mainCards = doc.DocumentNode.SelectNodes("//div[@class='css-1sw7q4x']");
for (int i = 0; i < mainCards.Count; i++)
{
    
    if (mainCards[i].Attributes["id"] != null)
    {
        var id = mainCards[i].Attributes["id"].Value; // Get ID of the card

        var card = mainCards[i];

        // Select node where id == var id and class == var adTitleClassName
        Print(card.SelectSingleNode($"//div[@id='{id}']//*[@class='{adTitleClassName}']").InnerText, DEBUG_TYPE.DO_NOT_PRINT);
    }
    else
    {
        // ID == NULL
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.