Выделение текста из некоторых элементов внутри div и игнорирование других элементов. HTML Agility Pack - PullRequest
0 голосов
/ 09 марта 2020

Я пытаюсь создать инструмент для поиска новостей для новостного сайта. У меня проблемы с выбором соответствующего текста, так как текст разделен на несколько разных элементов. Я использую HTML Agility Pack, и я попытался выбрать текст (// text ()) из основного div, но когда я делаю это, я получаю много ненужного текста, например javascript код. Как я могу выбрать текст из некоторых вложенных элементов и игнорировать другие элементы?

<div class="texto_container paywall">
  Some text I want
  <a href="https://www.sabado.pt/sabermais/ana-gomes" target="_blank" rel="noopener">
    Text I want
  </a> 
    sample of text I want
  <em>
    another text i want
  </em>
  <aside class="multimediaEmbed contentRight">
      A lot of nested elements here with some text I dont want
  </aside>
  <div class="inContent">
      A lot of nested elements here with some text I don't want
  </div>
  
  Back to the text I want!
  
  <twitter-widget class="twitter-tweet twitter-tweet-rendered" id="twitter-widget-0" >
    Don't want any of this text located in nested elements!
  </twitter-widget>
  
  <p>
    Final revelant text i want to collect!
  </p> 
  
</div>

РЕДАКТИРОВАТЬ

Я пытался использовать XPath для исключения ненужных тегов, но я все еще получаю текстовые узлы из эти теги в результате.

var parse_me = htmlDoc.DocumentNode.SelectNodes("//div[@class='texto_container paywall']//text()[not(parent::aside)][not(parent::div[@class='inContent'])][not(parent::twitter-widget)]");

Я думаю, что этот код не работает, потому что в тегах, которые я не хочу включать в текст, родительские узлы не являются тегом "main", потому что это внутри множества вложенных тегов.

РЕДАКТИРОВАТЬ

После некоторых размышлений и исследований я исправил предыдущую проблему, используя вместо этого ancestor :: parent :: , и я избавился от части предполагаемого текста. Но я все еще не могу избавиться от текста twitter-widget , поскольку он всегда возвращает нулевой узел, даже если XPath скопирован из инструмента проверки Google Chrome.

var Twitter_Node = htmlDoc.DocumentNode.SelectSingleNode("//*[@id='twitter - widget - 0']");

Возвращается как ноль. Как это возможно? XPath был скопирован с Chrome.

Ответы [ 2 ]

0 голосов
/ 09 марта 2020

Я использую ScrapySharp nuget, который добавлен в моем примере ниже (возможно, HtmlAgilityPack предлагает ту же функциональность, встроенную в него, я просто привык к ScrapySharp от лет go)

Вы можете просто пунктуально извлеките все ненужные тексты, а затем замените их вхождения в основном тексте div на пустую строку, удалив их из окончательного результата.

    var doc = new HtmlDocument();
    doc.Load(@"C:\Desktop\z.html"); //I created an html with your sample HTML set as the html body

    List<string> textsIWant = new List<string>();

    var textsIdoNotWant = new List<string>();
    //text I do not want
    var aside = doc.DocumentNode.CssSelect(".multimediaEmbed.contentRight").FirstOrDefault();
    if (aside != null)
    {
        textsIdoNotWant.Add(aside.InnerText);
    }

    var inContent = doc.DocumentNode.CssSelect(".inContent").FirstOrDefault();
    if (inContent != null)
    {
        textsIdoNotWant.Add(inContent.InnerText);
    }

    var twitterWidget = doc.DocumentNode.CssSelect("#twitter-widget-0").FirstOrDefault();
    if (twitterWidget != null)
    {
        textsIdoNotWant.Add(twitterWidget.InnerText);
    }

    var div = doc.DocumentNode.CssSelect(".texto_container.paywall").FirstOrDefault();
    if (div != null)
    {
        var text = div.InnerText;
        foreach (var textIDoNotWant in textsIdoNotWant)
        {
            text = text.Replace(textIDoNotWant, string.Empty);
        }

        textsIWant.Add(text);
    }

    foreach (var text in textsIWant)
        Console.WriteLine(text);

enter image description here

0 голосов
/ 09 марта 2020

Вы можете попытаться исключить текст из указанных тегов c:

//body//text()[not(parent::aside)][not(parent::div[@class="inContent"])][not(parent::twitter-widget)]

Вы можете использовать concat, но это сложнее, так как вам нужно знать номер и положение каждого тега в " цепь ":

concat(//body//div[@class="texto_container paywall"]/text()[1],//body//a[@href]/text(),//body//div[@class="texto_container paywall"]/text()[2],//body//em/text(),//body//div[@class="texto_container paywall"]/text()[5],//body//p/text())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...