Python正则表达式从旧HTML中抓取段落

时间:2016-05-14 19:09:35

标签: python html regex

我正在努力将旧网页上的旧内容从一些旧的HTML中传输到新的WordPress网站。我正在使用Python来做到这一点。我想

  1. 使用urllib.request
  2. 从旧HTML页面获取内容
  3. 使用正则表达式获取HTML <p>元素的文本,这些元素具有将其标识为文本正文的类
  4. 使用XML-RPC方法将内容上传到新的WordPress网站。
  5. 我很喜欢#1和#3。我遇到的问题是#2,编写正则表达式来捕获内容。

    内容采用不同格式的段落。以下是我试图使用正则表达式提取内容的两个段落的两个代表性示例。

    第1段

    <p class=bodyDC style='text-indent:12.0pt'><span style='font-size:14.0pt;
    mso-bidi-font-size:10.0pt'>We have no need to fear the future.&quot; So said
    bishop-elect H. George Anderson at a news conference immediately following his election as 
    bishop of the Evangelical Lutheran Church in America. &quot;[The
    future] belongs­ to God, untouched by human hands.&quot; At the beginning of a
    new ministry of leadership and pastoral oversight, such words from a bishop are
    obviously designed to project confidence and a profound sense of trust in the
    mission of the Church. They are words designed to inspire and empower the
    people of God for ministry.<o:p></o:p></span></p>
    

    第2段

    <p class=BODY><span style='font-size:14.0pt;mso-bidi-font-size:10.0pt'>Ages
    ago, another prophet of the people stood at his station and peered into the
    future. The<span style="mso-spacerun: yes">  </span>prophet Habakkuk poised on
    the rampart, scanned the horizon for the approaching enemy he knew was coming.
    As he waited, Habakkuk prayed to God asking why God was unresponsive to all
    this violence and destruction. In Habakkuk chapter 2 the prophet records God's
    answer to his questions about the future. God says to the fearful one, &quot;For
    there is still a vision for the appointed time;… If it seems to tarry, wait for
    it; it will surely come, it will not delay…the righteous live by faith&quot;
    (2:3-4).<o:p></o:p></span></p>
    

    理想情况下,我的正则表达式将通过其BODY或bodyDC类识别内容段落。一旦识别出包含文本内容的段落,它就会忽略文本内容之前和之后的所有HTML元素,并简单地抓取文本内容。

    到目前为止,我所使用的正则表达式仍在进行中: post_content_re = re.compile(r'<p class=(body\w*)(.*?>)(<.*?>)*([a-z])', re.IGNORECASE)

    我对正则表达式部分的解释: class=(body\w*)应匹配BODY或bodyDC,但它不匹配,它只匹配BODY,我不知道为什么

    (.*?>)匹配段落元素

    中的其余属性

    (<.*?>)*匹配&lt;&gt;中包含的0个或更多html元素在段落元素之后

    ([a-z])我想要获取的内容将在任何HTML元素之后。现在我只测试一个字母,而不是完整的段落文本,因为我还在测试。

    我得到的比赛都是这样的:

    1. BODY - 但我期待BODYbodyDC

    2. > - 这是结束&gt;类BODY

    3. 的p元素
    4. <span style='font-size:14.0pt;mso-bidi-font-size:10.0pt'> - 这是P元素

    5. 之后的span元素
    6. A - 这是span元素之后的第一个字母

    7. 基本上,我的RE匹配上面段落#2之类的段落,但不像段落#1。我不知道为什么,而且我被卡住了。

      感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

虽然(正如有人评论的那样)你不应该像这样解析HTML,但对于这种一次性的工作,这种解决方案可能会起作用。

您的正则表达式不适用于第一段,因为.与换行符不匹配,并且您的标记中有换行符 。您可以使用[\S\s]等技巧来匹配所有字符,包括换行符。

这个删除段落末尾的标签,但我希望它仍有帮助:

for g1, g2, content in re.findall("<p (class=bodyDC|class=BODY)[^><]*>(<[\S\s]*?>)*([\S\s]*?)<\\/p>", str1):
    print content

有点解释:

<p (class=bodyDC|class=BODY)[^><]*>匹配开头的段落标记
<p:标签的开头
(class=bodyDC|class=BODY):两个类属性之一
[^><]*:标记内的任何其他属性
>:标记的结尾

(<[\S\s]*?>)*匹配任意数量的标签
<:标签的开头
[\S\s]*?:任何其他属性(也可能使用[^><]*
>:标记结尾

([\S\s]*?)匹配任何文字。这是第3组,这基本上就是内容。 (加上最后的标签。)

<\/p>匹配结束段落标记。 (注意,在代码中它实际上显示为<\\/p>,因为反斜杠必须在python字符串中进行转义。)

答案 1 :(得分:0)

我会按照两步的方法解决这个问题。

  • 首先收集所有感兴趣的段落
  • 第二次提取每个段落的文字

第一

解析所有具有所需类别的段落。

<p\s*(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*?\sclass=(['"]?)(?:body|bodydc)\1(?:\s|>)(?:([^<]*)|<(?!\/p)(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*>)*(?=<\/p>)

此正则表达式将执行以下操作:

  • 查找给定类的所有段落标记,但不包括关闭</p>
  • 避免了一些奇怪的边缘问题,例如<span onmouseover=" </p> ">
  • 由于正则表达式的限制,这不适用于<p>outside paragraph<p>inside paragraph</p>more text in the outside</p>
  • 等嵌套段落标记

请参阅Live Demo

第二

从每个段落中提取原始文本

(?:([^<]*)|<(?!\/p)(?:[^>=]|='[^']*'|="[^"]*"|=[^'"][^\s>]*)*>)

此正则表达式将执行以下操作:

  • 匹配原始文本和标记
  • 将原始文本放入捕获组1
  • 避免困难的边缘案例

请参阅Live Demo