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

2024-09-30 01:22:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在努力从一个网站上转移旧的内容,用一些旧的HTML,到他们的新的WordPress网站。我用Python来做这个。我正在努力

  1. 使用从旧的HTML页面获取内容urllib.请求在
  2. 使用正则表达式获取HTML<p>元素的文本,这些元素具有将它们标识为文本正文的类
  3. 使用XML-RPC方法将内容上载到新的WordPress站点。在

我同意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款

^{pr2}$

理想情况下,我的正则表达式将通过BODY或bodyDC的类来识别内容段落。一旦它识别出一个包含文本内容的段落,它就会忽略文本内容前面和后面的所有HTML元素,而只获取文本内容。在

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

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

(.*?>)匹配段落元素中的其余属性

(<.*?>)*匹配段落元素后包含的0个或多个html元素

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

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

  1. BODY-但我期望BODY或{}

  2. >-这是带有类主体的p元素的结束符

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

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

所以从本质上说,我的RE是匹配上面第2段的段落,而不是第1段。我不知道为什么,我被卡住了。在

谢谢你的帮助。在


Tags: oftheto文本pt元素内容size
2条回答

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

您的regex不适用于第一段,因为.与换行符不匹配,并且您的标记中有一个换行符。您可以使用[\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):两个类属性之一
[^><]*:标记内的任何其他属性
>:标记的结尾

{8个匹配的<:标记的开头
[\S\s]*?:任何其他属性(也可以使用[^><]*
>:标记结束

([\S\s]*?)匹配任何文本。这是第三组,基本上是内容。(加上末尾的标签。)

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

我将采取两步走的方法来解决这个问题。在

  • 首先收集所有感兴趣的段落
  • 第二,从每一段中摘录课文

第一个

解析出所有具有所需类的段落。在

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

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

  • 查找给定类的所有段落标记,直到但不包括结束符</p>
  • 避免一些奇怪的边缘情况问题,如<span onmouseover=" </p> ">
  • 由于regex的限制,这将不适用于嵌套段落标记,如<p>outside paragraph<p>inside paragraph</p>more text in the outside</p>

Live Demo

第二个

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

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

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

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

Live Demo

相关问题 更多 >

    热门问题