Beautiful Soup 4自定义属性顺序输出

问题描述 投票:0回答:2

[我想在BS4中创建一个自定义输出格式化程序,它将以一种不是字母顺序的特定方式重新排列XML中标记属性的顺序。

例如,我要输出以下标签:

<word form="συ" head="2610" id="2357" lemma="συ" postag="p-s----n-" relation="ExD_AP"/>

as:

<word id="2357" head="2610" postag="p-s----n-" form="συ" lemma="συ" relation="ExD_AP"/>

BS4的文档提供了从哪里开始的线索。他们给出了以下示例:

from bs4.formatter import HTMLFormatter
class UnsortedAttributes(HTMLFormatter):
    def attributes(self, tag):
        for k, v in tag.attrs.items():
            if k == 'm':
                continue
            yield k, v
print(attr_soup.p.encode(formatter=UnsortedAttributes()))

这将创建一个自定义HTML输出格式化程序,该格式化程序将按输入属性的顺序保留属性,并忽略某些标签,但是我不知道如何更改此格式,以便按我希望的顺序输出。谁能帮帮我?

python-3.x xml dom beautifulsoup attributes
2个回答
2
投票

怎么样?

from simplified_scrapy.simplified_doc import SimplifiedDoc
html ='''
<word form="συ" head="2610" id="2357" lemma="συ" postag="p-s----n-" relation="ExD_AP"/>
'''
def toString(ele):
  order = ['id','head','postag','from','lemma','relation']
  result = '<'+ele.tag
  for p in order:
    result+=' {}="{}"'.format(p,ele[p])
  return result+'/>'
doc = SimplifiedDoc(html)
ele = doc.word
print (toString(ele))

结果:

<word id="2357" head="2610" postag="p-s----n-" from="None" lemma="συ" relation="ExD_AP"/>

0
投票

严格来说,我对自己的问题有一个答案,但是要以我希望的方式实际实施它需要更多的工作。这是操作方法。

作为XMLFormatter(如果使用HTML,则为HTMLFormatter)的子类,将其命名为所需的名称。我选择了“ SortAttributes”。编写函数“ attributes”,以便它将按所需顺序返回元组列表:[[(attribute1,value1),(attribute2,value2)等]。我的看起来可能很冗长,但我这样做是因为我使用的是非常不一致的XML。

from bs4 import BeautifulSoup
from bs4.formatter import XMLFormatter


class SortAttributes(XMLFormatter):
    def attributes(self, tag):
        """Reorder a tag's attributes however you want."""
        attrib_order = ['id', 'head', 'postag', 'relation', 'form', 'lemma']
        new_order = []
        for element in attrib_order:
            if element in tag.attrs:
                new_order.append((element, tag[element]))
        for pair in tag.attrs.items():
            if pair not in new_order:
                new_order.append(pair)
        return new_order


xml_string = '''
<word form="συ" head="2610" id="2357" lemma="συ" postag="p-s----n-" relation="ExD_AP"/>
'''
soup = BeautifulSoup(xml_string, 'xml')
print(soup.encode(formatter=SortAttributes()))

这将输出我想要的:

<word id="2357" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/>

方便地,我可以使用相同的编码方法对整个文档执行此操作。但是,如果我以字符串形式将其写入文件,则所有标签都将首尾相连。样本如下:

<sentence id="783"><word id="2357" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/><word id="2358" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/><word id="2359" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/></sentence>

而不是我想要的东西:

<sentence id="783">
  <word id="2357" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/>
  <word id="2358" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/>
  <word id="2359" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/>
</sentence>

要解决这个问题,我不能只是.prettify它,因为prettify将属性重新排列为字母顺序。我将不得不使用XMLFormatter子类进入更多细节。希望以后有人对您有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.