【问题标题】:Find all elements with text string?查找所有带有文本字符串的元素?
【发布时间】:2018-07-17 23:07:16
【问题描述】:

我正在尝试删除所有包含特定文本字符串的 html 元素(标签)。我有 2376 个 html 文档,都具有不同的 doctype 标准。有些甚至没有文档类型(可能与这个问题无关)。

所以,我正在寻找一个文本字符串,上面写着“如何引用这篇论文”,我发现它包含在 <p>-tag<h4>-tag<legend>-tag 中。

<p>-tag 经常是这个样子,

<p style="text-align : center; color : Red; font-weight : bold;">How to cite this paper:</i></p>

&lt;h4&gt;-tag 经常是这个样子,

<h4>How to cite this paper:</h4>Antunes, P., Costa, C.J. &amp; Pino, J.A. (2006).

&lt;legend&gt;-tag 看起来像这样,

<legend style="color: white; background-color: maroon; font-size: medium; padding: .1ex .5ex; border-right: 1px solid navy; border-bottom: 1px solid navy; font-weight: bold;">How to cite this paper</legend>

手头的任务是找到这些标签并将它们从文件中删除,然后再次保存文件。我确实有更多标签要删除,但需要一些帮助来理解 HAP 和 XPath,以及如何根据它们的值或其他独特数据定位特定标签。

到目前为止,我已经用 C# 编写了这段代码,它是一个控制台应用程序。 这是我的主要(抱歉缩进不好),

//Variables
string Ext = "*.html";
string folder = @"D:\websites\dev.openjournal.tld\public\arkivet\";
IEnumerable<string> files = GetHTMLFiles(folder, Ext);
List<string> cite_files = new List<string>();            
var doc = new HtmlDocument();

//Loop to match all html-elements to query
foreach (var file in files)
{
 try
   {
      doc.Load(file);
      cite_files.Add(doc.DocumentNode.SelectNodes("//h4[contains(., 'How to cite this paper')]").ToString()); 

     cite_files.Add(doc.DocumentNode.SelectNodes("//p[contains(., 'How to cite this paper')]").ToString());
   }                
                    catch (Exception Ex)
                    {
                        Console.WriteLine(Ex.Message);
                    }
                }

                //Counts numbers of hits and prints data to user
                int filecount = files.Count();
                int citations = cite_files.Count();            
                Console.WriteLine("Number of files scanned: " + filecount);
                Console.WriteLine("Number of citations: {0}", citations);

                // Program end
                Console.WriteLine("Press any key to close program....");
                Console.ReadKey();

这是在目录中查找文件的私有方法,

//List all HTML-files recursively and return them to a list 
 public static IEnumerable<string> GetHTMLFiles(string directory, string Ext)
    {
        List<string> files = new List<string>();

        try
        {
            files.AddRange(Directory.GetFiles(directory, Ext, SearchOption.AllDirectories));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }            
        return files;
    }

独特的东西似乎是“如何引用这篇论文”,所以我试图找到包含这些确切单词的所有特定标签,然后将它们删除。我的记事本显示应该有 1094 个包含此短语的文件,所以我试图全部获取。 :)

非常感谢任何帮助! :)

【问题讨论】:

    标签: c# html xpath html-agility-pack


    【解决方案1】:

    Html Agility Pack 支持 LINQ 选择器,这在这种情况下非常方便。根据上面的示例给出一些 HTML:

    var html =
    @"<html><head></head><body>
    
    <!-- selector match: delete these nodes -->
    <p style='text-align: center; color: Red; font-weight: bold;'>How to cite this paper:</i></p>
    <h4> How to cite this paper:</h4> Antunes, P., Costa, C.J. & amp; Pino, J.A. (2006).
    <legend style='color: white; background-color: maroon; font-size: medium; padding: .1ex .5ex; border-right: 1px solid navy; border-bottom: 1px solid navy; font-weight: bold;'>How to cite this paper </legend>
    <div><p><i><b>How to cite this paper (NESTED)</b></i></p></div>
    
    <!-- no match: keep these nodes -->
    <p>DO NOT DELETE - How to cite</p>
    <h4>DO NOT DELETE - cite this paper:</h4>
    <legend>DO NOT DELETE</legend>
    
    </body></html>";
    

    你可以创建一个应该被搜索的标签集合,选择匹配的节点,然后像这样删除它们:

    var tagsToDelete = new string[] { "p", "h4", "legend" };
    var nodesToDelete = new List<HtmlNode>();
    
    var document = new HtmlDocument();
    document.LoadHtml(html);
    foreach (var tag in tagsToDelete)
    {
        nodesToDelete.AddRange(
            from searchText in document.DocumentNode.Descendants(tag)
                where searchText.InnerText.Contains("How to cite this paper")
                select searchText
        );
    }
    
    foreach (var node in nodesToDelete) node.Remove();
    
    document.Save(OUTPUT);
    

    结果如下:

    <html><head></head><body>
    
    <!-- XPath match: delete these nodes -->
    
     Antunes, P., Costa, C.J. & amp; Pino, J.A. (2006).
    
    <div></div>
    
    <!-- no match, keep these nodes -->
    <p>DO NOT DELETE - How to cite</p>
    <h4>DO NOT DELETE - cite this paper:</h4>
    <legend>DO NOT DELETE</legend>
    
    </body></html>
    

    【讨论】:

    • 非常感谢您花时间帮助我。非常感激。现在,如果我也想删除节点怎么办?由于我不想要空节点,我宁愿删除 InnerText 和节点。还是 node.Remove() 实际上也删除了节点?我会在早上试一试。再次感谢您提供非常好的答案。 :)
    • @ChristerJohansson - 上面的示例代码确实删除了匹配的ph4legend 节点,如结果所示。 :)
    • 啊,好的。那我明天再补一下。再次谢谢你。 :)
    • 我似乎无法让它工作。它不会向 nodesToDelete 列表返回任何内容。我正在使用 VS 2017 社区。我尝试进行 foreach 以查看列表中是否有内容,但它是空的。 VS 不表示任何错误。我做了一个小提琴,dotnetfiddle.net/p70zWr
    • 我的示例是加载 HTML string,但您正在加载 文件路径。所以你需要使用document.Load(file)不是 document.LoadHtml(file);
    猜你喜欢
    • 2011-03-06
    • 2017-05-17
    • 2022-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 2023-04-01
    相关资源
    最近更新 更多