【问题标题】:How to extract text and tag attributes from xml using BeautifulSoup如何使用 BeautifulSoup 从 xml 中提取文本和标签属性
【发布时间】:2019-11-17 18:15:24
【问题描述】:

我想从 xml 下方提取文本以及宽度、高度、顶部、左侧和页码,并将其附加到数据框。

   <page number="1" position="absolute" top="0" left="0" height="1188" width="918">
       <fontspec id="0" size="21" family="MOFZXD+AvenirNext-DemiBold" color="#231f20"/>
       <fontspec id="1" size="25" family="MOFZXD+MyriadPro-Regular" color="#231f20"/>

       <text top="375" left="708" width="168" height="33" font="0"><b>LISTING # 1131</b></text>
       <text top="1049" left="657" width="92" height="32" font="1">1.03 +/- </text>
       <text top="1049" left="750" width="51" height="35" font="1">Acre</text>
       <text top="1089" left="657" width="178" height="27" font="2">Tax Map and Parcel:</text>
   </page>


   <page number="2" position="absolute" top="0" left="0" height="1188" width="918">
       <fontspec id="6" size="23" family="MOFZXD+Baskerville" color="#57585a"/>
       <fontspec id="7" size="10" family="LGVTJF+Avenir-Roman" color="#231f20"/>
       <text top="827" left="681" width="107" height="33" font="6">Andy Cox </text>
       <text top="861" left="681" width="186" height="17" font="7">COMMERCIAL SALES SPECIALIST</text>
   </page>

我尝试使用以下代码,但结果只包含重复值。

for message in soup.findAll('page'):
    page_number = re.findall(r'number=\"(\d*?)\"', str(message))[0]
    for text in soup.findAll('text'):
        content = text.text

        #print(font_value)
        height_value = re.findall(r'height="(\d*?)"',str(text))[0]
        left_value = re.findall(r'left="(\d*?)"',str(text))[0]
        top_value = re.findall(r'top="(\d*?)"',str(text))[0]
        width_value = re.findall(r'top="(\d*?)"',str(text))[0]

        df = df.append({'Page Number':page_number,'Content':content,'Top':top_value,'Left':left_value,'Width':width_value,'Height':height_value},ignore_index=True)

结果

    Page Number Content     Top Left    Width   Height
1   LISTING  #1131  375 708 375 33
1   1.03 +/-    1049    657 1049    32
1   Acre    1049    750 1049    35
1   Tax Map and Parcel: 1089    657 1089    27
2   Andy Cox    827 681 107 33
2   COMMERCIAL SALES SPECIALIST 861 681 186 17

【问题讨论】:

  • 您应该只找到文本标签,然后访问它们的属性。我不确定我是否了解您目前在做什么。此外,BeautifulSoup 确实更适合解析 HTML。我推荐 lxml 来满足你所有的 xml 解析需求。
  • RESULT 游览 预期结果吗?
  • 如果你也分享一些有代表性的数据会很好。请参阅:minimal reproducible example.
  • @AlexanderCécile - 问题中有示例标记。
  • @wwii 是的,我看到了,我只是想确保格式一致。

标签: python regex xml beautifulsoup


【解决方案1】:

使用BeautifulSoup 查找您想要的标签并从标签中提取信息。

import operator
from bs4 import BeautifulSoup
whatiwant = operator.itemgetter('top','left','width','height')
#soup = BeautifulSoup(s,'lxml')
soup = BeautifulSoup(s,'html.parser')
for page in soup.findAll('page'):
    for t in page.findAll('text'):
        print(page['number'], t.text, whatiwant(t))

【讨论】:

    【解决方案2】:

    我选择使用 BeautifulSoup 来解析 XML 一次,它工作得很好。我在你的数据中添加了一个根标签,这样我的 IDE 就不会抱怨了。

    代码:

    import pandas as pd
    from bs4 import BeautifulSoup
    
    col_names = ['page_number', 'elem_text', 'elem_top', 'elem_left', 'elem_width', 'elem_height']
    
    with open('../resources/page_text_xml_data.xml') as file_in:
        soup = BeautifulSoup(file_in, features='xml')
    
    row_dicts = []
    
    for curr_page in soup.find('root').find_all('page', recursive=False):
        curr_page_num = curr_page['number']
        for curr_text_elem in curr_page.find_all('text', recursive=False):
            row_dicts.append(
                {'page_number': curr_page_num, 'elem_text': curr_text_elem.text.strip(), 'elem_top': curr_text_elem['top'],
                 'elem_left': curr_text_elem['left'], 'elem_width': curr_text_elem['width'],
                 'elem_height': curr_text_elem['height']})
    
    df_1 = pd.DataFrame(row_dicts)
    

    数据帧内容:

          page_number  elem_text                      elem_top    elem_left    elem_width    elem_height
    --  -------------  ---------------------------  ----------  -----------  ------------  -------------
     0              1  LISTING # 1131                      375          708           168             33
     1              1  1.03 +/-                           1049          657            92             32
     2              1  Acre                               1049          750            51             35
     3              1  Tax Map and Parcel:                1089          657           178             27
     4              2  Andy Cox                            827          681           107             33
     5              2  COMMERCIAL SALES SPECIALIST         861          681           186             17
    

    如果您有任何问题,请告诉我:)

    【讨论】:

      猜你喜欢
      • 2013-07-01
      • 1970-01-01
      • 2017-10-14
      • 1970-01-01
      • 1970-01-01
      • 2015-08-12
      • 1970-01-01
      • 1970-01-01
      • 2014-05-22
      相关资源
      最近更新 更多