Python 如何在保留html标记/结构的同时查找/替换html中的文本

Python 如何在保留html标记/结构的同时查找/替换html中的文本,python,html,html-parsing,Python,Html,Html Parsing,我使用regexps转换文本,但我想保留HTML标记。 e、 g.如果我想将“堆栈溢出”替换为“堆栈下溢”,则应按照以下步骤进行操作: 预期:如果输入是堆栈溢出,我必须获得堆栈下溢(即字符串替换完成,但 标记仍然存在…在处理HTML时使用DOM库,而不是正则表达式: lxml:解析器、文档和HTML序列化程序。还可以使用BeautifulSoup和html5lib进行解析 BeautifulSoup:解析器、文档和HTML序列化程序 html5lib:一个解析器。它有一个序列化程序 Eleme

我使用regexps转换文本,但我想保留HTML标记。 e、 g.如果我想将“堆栈溢出”替换为“堆栈下溢”,则应按照以下步骤进行操作: 预期:如果输入是
堆栈溢出
,我必须获得
堆栈下溢
(即字符串替换完成,但
标记仍然存在…

在处理HTML时使用DOM库,而不是正则表达式:

  • lxml:解析器、文档和HTML序列化程序。还可以使用BeautifulSoup和html5lib进行解析
  • BeautifulSoup:解析器、文档和HTML序列化程序
  • html5lib:一个解析器。它有一个序列化程序
  • ElementTree:文档对象和XML序列化程序
  • cElementTree:作为C扩展实现的文档对象
  • HTMLParser:一个解析器
  • Genshi:包括解析器、文档和HTML序列化程序
  • xml.dom.minidom:标准库中内置的文档模型,html5lib可以对其进行解析
从……偷来的


其中我推荐lxml、html5lib和BeautifulSoup。

或者是您的答案。

使用或提供的html解析器。另一个选项是使用XSLT转换().

我不认为目前发布的DOM/HTML解析器库建议解决了给定示例中的特定问题:
溢出
应该被
下溢
替换,仅当呈现文档中的
堆栈
之前,不管它们之间是否有标记。这样的库是必要的部分不过,解决办法是

假设标签永远不会出现在词的中间,一个解决方案是

  • 处理DOM,标记所有文本节点并插入唯一标识符 在每个标记的开头(例如单词)
  • 将文档呈现为纯文本
  • 用正则表达式搜索并替换纯文本,正则表达式使用组进行匹配、保留和删除 在每个标记的开头标记唯一标识符
  • 从纯文本中提取具有标记的唯一标识符的所有令牌
  • 通过删除唯一标识符并替换匹配的标记来处理DOM 用相应的已更改标记标记唯一标识符
  • 将处理后的DOM渲染回HTML
  • 例子: 在1.HTMLDOM中

    stack <sometag>overflow</sometag>
    
    3.中需要的正则表达式是
    #(\d+);stack\s+#(\d+);overflow\b
    和替换的
    #\1;stack%\2;underflow
    。请注意,唯一标识符中只有第二个单词通过将
    更改为
    %
    来标记,因为第一个单词没有更改

    在4.中,从生成的纯文本中提取具有编号为
    2
    的唯一标识符的单词
    underflow
    ,因为它是通过将
    #
    更改为
    %
    来标记的

    在5.中,所有
    #(\d+)
    标识符从DOM的文本节点中删除,同时在提取的单词中查找它们的数字。找不到数字
    1
    ,因此
    #1;stack
    被简单地替换为
    stack
    。数字
    2
    被替换的单词
    underflow
    ,因此
    #2;overflow
    替换ode>下溢


    最后在6中,DOM呈现回HTML文档“堆栈下溢”。

    注意,任意替换不能明确地进行。请考虑以下示例:

    1) HTML:

    可能的结果:

    AX<tag>B</tag>
    A<tag>XB</tag>
    
    W<tag />XYZ
    W<tag>X</tag>YZ
    W<tag>XY</tag>Z
    W<tag>XYZ</tag>
    WX<tag />YZ
    WX<tag>Y</tag>Z
    WX<tag>YZ</tag>
    WXY<tag />Z
    WXY<tag>Z</tag>
    WXYZ
    
    可能的结果:

    AX<tag>B</tag>
    A<tag>XB</tag>
    
    W<tag />XYZ
    W<tag>X</tag>YZ
    W<tag>XY</tag>Z
    W<tag>XYZ</tag>
    WX<tag />YZ
    WX<tag>Y</tag>Z
    WX<tag>YZ</tag>
    WXY<tag />Z
    WXY<tag>Z</tag>
    WXYZ
    
    WXYZ
    WXYZ
    WXYZ
    WXYZ
    WXYZ
    WXYZ
    WXYZ
    WXYZ
    WXYZ
    WXYZ
    

    什么样的算法适用于您的案例在很大程度上取决于可能的搜索模式的性质和处理歧义所需的规则。

    尝试一些有趣的东西。这有点管用。我的朋友喜欢我把这个脚本附加到文本区域,让他们“翻译”东西。我想你真的可以用它做任何事。无聊的。如果你打算使用它,请检查代码几次,它是有效的,但我对所有这些都是新手。我想我开始学习php已经有两三个星期了

    
    <?php
    
    $html = ('<div style="border: groove 2px;"><p>Dear so and so, after reviewing your application I. . .</p><p>More of the same...</p><p>sincerely,</p><p>Important Dude</p></div>');
    
    $oldWords = array('important', 'sincerely');
    
    $newWords = array('arrogant', 'ya sure');
    
    // function for oldWords
    function regex_oldWords_word_list(&$item1, $key)
    {
    
        $item1 = "/>([^<>]+)?\b$item1(tionally|istic|tion|ance|ence|less|ally|able|ness|ing|ity|ful|ant|est|ist|ic|al|ed|er|et|ly|y|s|d|'s|'d|'ve|'ll)?\b([^<>]+)?/";
    
    }
    
    // function for newWords
    function format_newWords_results(&$item1, $key)
    {
    
        $item1 = ">$1<span style=\"color: red;\"><em> $item1$2</em></span>$3";
    
    }
    
    // apply regex to oldWords
    array_walk($oldWords, 'regex_oldWords_word_list');
    
    // apply formatting to newWords
    array_walk($newWords, 'format_newWords_results');
    
    //HTML is not always as perfect as we want it
    $poo = array('/  /', '/>([a-zA-Z\']+)/', '/’/', '/;([a-zA-Z\']+)/', '/"([a-zA-Z\']+)/', '/([a-zA-Z\']+)</', '/\.\.+/', '/\. \.+/');
    
    $unpoo = array(' ', '> $1', '\'', ';  $1', '"  $1', '$1  <', '. crap taco.', '. crap taco with cheese.');
    
    //and maybe things will go back to normal sort of
    $repoo = array('/>  /', '/;  /', '/"  /', '/  </');
    
    $muck = array('> ', ';', '"',' <');
    
    //before
    echo ($html);
    
    //I don't know what was happening on the free host but I had to keep stripping slashes
    //This is where the work is done anyway.
    $html = stripslashes(preg_replace($repoo , $muck , (ucwords(preg_replace($oldWords , $newWords , (preg_replace($poo , $unpoo , (stripslashes(strtolower(stripslashes($html)))))))))));
    
    //after
    echo ('<hr/> ' . $html);
    
    //now if only there were a way to keep it out of the area between
    //<style>here</style> and <script>here</script> and tell it that english isn't math.
    
    ?>
    

    阅读此文并在为时已晚之前忏悔:
    A<tag>A</tag>A
    
    A+ -> WXYZ
    
    W<tag />XYZ
    W<tag>X</tag>YZ
    W<tag>XY</tag>Z
    W<tag>XYZ</tag>
    WX<tag />YZ
    WX<tag>Y</tag>Z
    WX<tag>YZ</tag>
    WXY<tag />Z
    WXY<tag>Z</tag>
    WXYZ
    
    
    <?php
    
    $html = ('<div style="border: groove 2px;"><p>Dear so and so, after reviewing your application I. . .</p><p>More of the same...</p><p>sincerely,</p><p>Important Dude</p></div>');
    
    $oldWords = array('important', 'sincerely');
    
    $newWords = array('arrogant', 'ya sure');
    
    // function for oldWords
    function regex_oldWords_word_list(&$item1, $key)
    {
    
        $item1 = "/>([^<>]+)?\b$item1(tionally|istic|tion|ance|ence|less|ally|able|ness|ing|ity|ful|ant|est|ist|ic|al|ed|er|et|ly|y|s|d|'s|'d|'ve|'ll)?\b([^<>]+)?/";
    
    }
    
    // function for newWords
    function format_newWords_results(&$item1, $key)
    {
    
        $item1 = ">$1<span style=\"color: red;\"><em> $item1$2</em></span>$3";
    
    }
    
    // apply regex to oldWords
    array_walk($oldWords, 'regex_oldWords_word_list');
    
    // apply formatting to newWords
    array_walk($newWords, 'format_newWords_results');
    
    //HTML is not always as perfect as we want it
    $poo = array('/  /', '/>([a-zA-Z\']+)/', '/’/', '/;([a-zA-Z\']+)/', '/"([a-zA-Z\']+)/', '/([a-zA-Z\']+)</', '/\.\.+/', '/\. \.+/');
    
    $unpoo = array(' ', '> $1', '\'', ';  $1', '"  $1', '$1  <', '. crap taco.', '. crap taco with cheese.');
    
    //and maybe things will go back to normal sort of
    $repoo = array('/>  /', '/;  /', '/"  /', '/  </');
    
    $muck = array('> ', ';', '"',' <');
    
    //before
    echo ($html);
    
    //I don't know what was happening on the free host but I had to keep stripping slashes
    //This is where the work is done anyway.
    $html = stripslashes(preg_replace($repoo , $muck , (ucwords(preg_replace($oldWords , $newWords , (preg_replace($poo , $unpoo , (stripslashes(strtolower(stripslashes($html)))))))))));
    
    //after
    echo ('<hr/> ' . $html);
    
    //now if only there were a way to keep it out of the area between
    //<style>here</style> and <script>here</script> and tell it that english isn't math.
    
    ?>