如何用BeautifulSoup连接两个html文件体?

2024-04-27 21:19:17 发布

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

我需要将两个html文件的主体连接到一个html文件中,中间用一点任意的html作为分隔符。我有用于此目的的代码,但当我从Xubuntu 11.10(或是11.04?)升级时停止了工作到12.10,可能是由于BeautifulSoup update(我目前使用的是3.2.1;我不知道以前的版本)或vim更新(我使用vim从纯文本文件自动生成html文件)。这是代码的精简版本:

from BeautifulSoup import BeautifulSoup
soup_original_1 = BeautifulSoup(''.join(open('test1.html')))
soup_original_2 = BeautifulSoup(''.join(open('test2.html')))
contents_1 = soup_original_1.body.renderContents()
contents_2 = soup_original_2.body.renderContents()
contents_both = contents_1 + "\n<b>SEPARATOR\n</b>" + contents_2
soup_new = BeautifulSoup(''.join(open('test1.html')))
while len(soup_new.body.contents):
    soup_new.body.contents[0].extract()
soup_new.body.insert(0, contents_both)                       

用于测试用例的两个输入文件的主体非常简单:contents_1is\n<pre>\nFile 1\n</pre>\n'contents_2is'\n<pre>\nFile 2\n</pre>\n'

我希望soup_new.body.renderContents()是这两个文本之间的分隔符文本的连接,但是所有<都变成了&lt;等等。-期望的结果是'\n<pre>\nFile 1\n</pre>\n\n<b>SEPARATOR\n</b>\n<pre>\nFile 2\n</pre>\n',这是我在操作系统更新之前得到的结果;当前的结果是'\n&lt;pre&gt;\nFile 1\n&lt;/pre&gt;\n\n&lt;b&gt;SEPARATOR\n&lt;/b&gt;\n&lt;pre&gt;\nFile 2\n&lt;/pre&gt;\n',这是非常无用的。

在将html作为字符串插入soup对象的主体时,如何使BeautifulSoup停止将<转换为&lt;等?或者我应该用一种完全不同的方式来做?(这是我在BeautifulSoup和大多数其他html解析方面的唯一经验,所以我想很可能就是这样。)

html文件是用vim从纯文本文件自动生成的(我使用的实际情况显然更复杂,并且涉及到自定义语法突出显示,这就是我这样做的原因)。完整的test1.html文件如下所示,而test2.html除了内容和标题之外都是相同的。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>~/programs/lab_notebook_and_printing/concatenate-html_problem_2013/test1.txt.html</title>
<meta name="Generator" content="Vim/7.3" />
<meta name="plugin-version" content="vim7.3_v10" />
<meta name="syntax" content="none" />
<meta name="settings" content="ignore_folding,use_css,pre_wrap,expand_tabs,ignore_conceal" />
<style type="text/css">
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #ffffff; white-space: pre-wrap; word-wrap: break-word }
body { font-family: monospace; color: #000000; background-color: #ffffff; font-size: 0.875em }
</style>
</head>
<body>
<pre>
File 1
</pre>
</body>
</html>

Tags: 文件ltgtnewhtmlcontentsbodycontent
3条回答

我的html文档和元素循环都有问题。我发现BeautifulSoup未能成功解析我的一些HTML文件。我最后在body标记中的所有元素周围插入了一个标记:

<body><span id="entirebody">
:
</span></body>

这意味着所有元素都包含在一个span元素中并成功处理。当我不这么做的时候,我想深入了解到底发生了什么,但这是解决你可能遇到的问题的一种方法。

def insertSpan(htmlString):
    '''
    Insert a span tag around all of body contents:

    <body><span id="entirebody">....</span></body>
    '''
    subRe = re.compile(r'(<body>)(.*)(<\/body>)', re.DOTALL)
    htmlString = subRe.sub("\g<1><span id=\"entirebody\">\g<2></span>\g<3>",htmlString)
    return htmlString

正如abarnert在对答案的评论中提到的,append有一个问题。

这个answer由Martijn Pieters♦ 完成任务。

从BeautifulSoup 4.4开始(7月15日发布),您可以使用:

import copy

document2.body.append(copy.copy(element))

试图将HTML作为文本来阅读,仅仅是为了将其插入HTML中,并且在编码和解码两个方向上进行斗争,这使得大量的额外工作变得非常困难。

最简单的事情就是不要那样做。你想把test2主体中的所有内容都插入test1主体中的所有内容之后,对吧?所以就这么做吧:

for element in soup_original_2.body:
    soup_original_1.body.append(element)

要先附加分隔符,只需对分隔符执行相同的操作:

b = soup.new_tag('b')
b.append('SEPARATOR')
soup.original_1.body.append(b)
for element in soup_original_2.body:
    soup_original_1.body.append(element)

就这样。

请参阅文档部分Modifying the tree,以获得涵盖所有这些内容的教程。

相关问题 更多 >