gpt4 book ai didi

Python XML 解析算法速度

转载 作者:行者123 更新时间:2023-12-01 04:54:50 25 4
gpt4 key购买 nike

我目前正在 heroku 上的 python-flask web 应用程序中解析以下形式的大型 XML 文件:

<book name="bookname">
<volume n="1" name="volume1name">
<chapter n="1">
<li n="1">li 1 content</li>
<li n="2">li 2 content</li>
</chapter/>
<chapter n="2">
<li n="1">li 1 content</li>
<li n="2">li 2 content</li>
</chapter/>
</volume>
<volume n="2" name="volume2name">
<chapter n="1">
<li n="1">li 1 content</li>
<li n="2">li 2 content</li>
</chapter/>
<chapter n="2">
<li n="1">li 1 content</li>
<li n="2">li 2 content</li>
</chapter/>
</volume>
</book>

我通过Flask解析、分析、显示的代码如下:

from lxml import etree
file = open("books/filename.xml")
parser = etree.XMLParser(recover=True)
tree = etree.parse(file, parser)
root = tree.getroot()

def getChapter(volume, chapter):
i = 0
data = []
while True:
try:
data.append(root[volumeList().index(volume)][chapter-1][i].text)
except IndexError:
break
i += 1
if data == []:
data = None
return data

def volumeList():
data = tree.xpath('//volume/@name')
return data

def chapterCount(volume):
currentChapter = 1
count = 0
while True:
data = getChapter(volume, currentChapter)
if data == None:
break
else:
count += 1
currentChapter += 1
return count

def volumeNumerate():
list = volumeList()
i = 1
dict = {}
for element in list:
dict[i] = element
i += 1
return dict

def render_default_values(template, **kwargs):
chapter = getChapter(session['volume'],session['chapter'])
count = chapterCount(session['volume'])
return render_template(template, chapter=chapter, count=count, **kwargs)

@app.route('/<volume>/<int:chapter>')
def goto(volume, chapter):
session['volume'] = volume
session['chapter'] = chapter
return render_default_values("index.html")

我遇到的问题是,每当 Flask 尝试渲染包含许多章节的卷时(当 ChapterCount(session['volume']) > 大约 50 左右时),页面的加载和处理需要花费一些时间很长时间。相比之下,如果应用程序正在加载少于 10/15 章的卷,则加载几乎是瞬时的,即使作为实时 Web 应用程序也是如此。因此,有没有一个好的方法可以优化它,并提高速度和性能?非常感谢!

(PS:作为引用,这是我旧的 getChapter 函数,我停止使用它,因为我不想在代码中引用单个“li”,并且希望代码能够处理任何通用 XML 文件。它不过比当前的 getChapter 函数快得多!:

def OLDgetChapter(volume, chapter):
data = tree.xpath('//volume[@name="%s"]/chapter[@n=%d]/li/text()'%(volume,chapter))
if data == []:
data = None
return data

非常感谢!

最佳答案

您听说过 BeautifulSoup 吗?

BeautifulSoup解析方面的繁琐工作xml对你来说,除了它是用 C 语言实现的。

我确信这会更快(并且更具可读性):

from bs4 import BeautifulSoup

filename = "test.xml"
soup = BeautifulSoup(open(filename), "xml")

def chapterCount(volume_name):
volume = soup.find("volume", attrs={"name": volume_name})
chapter_count = len(volume.find_all("chapter", recursive=False))
return chapter_count

def getChapter(volume_name, chapter_number):
volume = soup.find("volume", {"name": volume_name})
chapter = volume.find("chapter", {"n": chapter_number})
items = [ content for content in chapter.contents if content != "\n" ]
return "\n".join([ item.contents[0] for item in items ])


# from now on, it's the same as your original code

def render_default_values(template, **kwargs):
chapter = getChapter(session['volume'],session['chapter'])
count = chapterCount(session['volume'])
return render_template(template, chapter=chapter, count=count, **kwargs)

@app.route('/<volume>/<int:chapter>')
def goto(volume, chapter):
session['volume'] = volume
session['chapter'] = chapter
return render_default_values("index.html")

请注意,不仅是 getChapter函数会更快,但要点是,当您想通过chapterCount来计算特定卷中的章节时,您不必为每个章节迭代它。 。这两个功能现在完全相互独立。

两个函数的结果:

>>> print(chapterCount("volume1name"))
2

>>> print(getChapter("volume1name", 2))
li 1 content
li 2 content

编辑:

我只是asked a question看看是否有一种更快的方法来计算章节。请继续关注:) - 更新:答案是您可以使用recursive=False防止 BS 返回通过 find_all 找到的元素的整个树。或者,直接使用lxml .

编辑:

我刚刚注意到您调用render_default_values在你看来。你不应该这样做,或者至少你应该以不同的方式调用这个函数。因为“渲染默认值”意味着......嗯,渲染默认值

允许此函数基于全局变量 ( session ) 渲染其他内容被认为不太 Pythonic,并且可能导致意大利面条式代码(未知错误等)。

关于Python XML 解析算法速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27673349/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com