pandas 使用import lxml.etree作为ElementTree抓取xml数据

798qvoo8  于 2023-05-21  发布在  其他
关注(0)|答案(1)|浏览(84)

我正在学习如何使用XML抓取网站。我很熟悉html,但我注意到我试图抓取的一些网站有XML API。如果我没弄错的话,刮起来更快,也更简单。
我有以下示例代码。

txt = '''
<?xml version="1.0"?>
<DIV5 N="100" TYPE="HEADER">
   <HEAD>100: DIV5 Title</HEAD>
   <AUTH>
      <HED>Authority:</HED>
      <PSPACE>AUTHORITY SPACE</PSPACE>
   </AUTH>
   <SOURCE>
      <HED>Source:</HED>
      <PSPACE>Source Text.</PSPACE>
   </SOURCE>
   <DIV7 N="1" TYPE="SUB">
      <HEAD>1. DIV7Title 1</HEAD>
      <DIV8 N="1.1" TYPE="SECTION">
         <HEAD>1.1 DIV8Title 1</HEAD>
         <P> (1) Text 1</P>
      </DIV8>

      <DIV8 N="1.2" TYPE="SECTION">
         <HEAD>1.2 DIV8Title 2</HEAD>
         <P>(a) text 1 </P>
         <P>(ii) text 2 </P>
         <P>(2) text 2.1 </P>
      </DIV8>

      <DIV8 N="1.3" TYPE="SECTION">
         <HEAD>1.3 DIV8 Title 3</HEAD>
         <P> (ff) text 1 </P>
      </DIV8>
   </DIV7>
   <DIV6 N="A" TYPE="SUBPART">
      <HEAD>Subpart A: DIV6Title 1 </HEAD>
      <DIV7 N="2" TYPE="SUB">
         <HEAD>2 DIV7Title 2</HEAD>
         <DIV8 N="2.1" TYPE="SECTION">
            <HEAD>2.1 DIV8Title 1 </HEAD>
            <P>(a) text 1</P>
            <P>(b) text 2 </P>
            <P>(c) text 3</P>
         </DIV8>

         <DIV8 N="2.2" TYPE="SECTION">
            <HEAD>2.2 DIV8 Title2</HEAD>
            <P> (o) text</P>
         </DIV8>
      </DIV7>
      <DIV7 N="3" TYPE="SUB">
         <HEAD>3. DIV7 Title 3</HEAD>
         <DIV8 N="3.1" TYPE="SECTION">
            <HEAD>3.1 DIV8 Title 1</HEAD>
            <P>(r) text 1</P>
            <P>(s) text 2</P>
         </DIV8>
      </DIV7>
   </DIV6>
   <DIV6 N="B" TYPE="SUBPART">
      <HEAD>Subpart B: DIV6 Title 2</HEAD>
         <DIV8 N="12" TYPE="SECTION">
            <HEAD>12. DIV8 Title 1</HEAD>
            <P>7(a) text </P>
         </DIV8>
   </DIV6>
</DIV5>
'''

我有以下代码:

import lxml.etree as ElementTree

tree = ElementTree.ElementTree(ElementTree.fromstring(txt))
root = tree.getroot()

sub_parts = root.findall(".//DIV6")

for sub in sub_parts:
   l2_title = subpart.find('.//HEAD').text
   .
   .# Unsure what to do after this part
   .

我遇到的问题:

  1. DIV 5子节点是[HEAD, AUTH, SOURCE, DIV7, DIV6, DIV6]上面的代码似乎只抓取DIV 6及其子节点。代码完全跳过了它们的DIV 7兄弟节点及其子节点。如何同时解析两者?
    理想结局:
    | L2Ci| L2标题|L3Ci| L3标题|L4Ci| L4标题|L5Ci| L5标题|L6Ci| L 6标题|
    | --------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|
    | | | 1. |DIV 7标题1| 1.1| DIV 8标题1|||(一)|案文1|
    | | | 1. |DIV 7标题1| 1.2| DIV 8标题2|(a)|正文1|||
    | | | 1. |DIV 7标题1| 1.2| DIV 8标题2|(ii)|正文二|||
    | | | 1. |DIV 7标题1| 1.2| DIV 8标题2|(ii)|正文二|(二)|案文2.1|
    | | | 1. |DIV 7标题1| 1.3| DIV 8标题3|(ff)|正文1|||
    | A| DIV 6标题1| 2.| DIV 7标题2| 2.1| DIV 8标题1|(a)|正文1|||
    | A| DIV 6标题1| 2.| DIV 7标题2| 2.1| DIV 8标题1|(B)|正文二|||
    | A| DIV 6标题1| 2.| DIV 7标题2| 2.1| DIV 8标题1|(c)|案文3|||
    | A| DIV 6标题1| 2.| DIV 7标题2| 2.2| DIV 8标题2|(o)|正文1|||
    | A| DIV 6标题1| 3.第三章|DIV 7标题3| 3.1| DIV 8标题3|(r)|正文1|||
    | A| DIV 6标题1| 3.第三章|DIV 7标题3| 3.1| DIV 8标题3|(s)|正文二|||
    | B| DIV 6标题2|||十二岁|DIV 8标题1|(a)|正文|||
    谢谢你!
plicqrtu

plicqrtu1#

您可以“递归”地处理所有标签,而不是试图通过名称来查找标签。关于.iter()
您可以跟踪构建“行”所需的信息。
在这种情况下,每次遇到<P>标记时,“行”都被认为是完整的,您可以存储结果。
类似于:

columns = [
   'L2Ci', 'L2Ci', 'L2Title', 'L3Ci', 'L3Title', 
   'L4Ci', 'L4Title', 'L5Ci', 'L5Title', 'L6Ci', 
   'L6Title'
]

row = dict.fromkeys(columns)
rows = []

tag_type = None

for item in tree.iter():
   if item.attrib.get('TYPE', '') == 'SUBPART':
      # New sub-part, empty out all previously seen values
      for key in row:
         row[key] = None
      row['L2Ci'] = item.attrib['N']
      tag_type = 'L2Title'

   if item.attrib.get('TYPE', '') == 'SUB':
      row['L3Ci'] = item.attrib['N']
      tag_type = 'L3Title'
  
   if item.attrib.get('TYPE', '') == 'SECTION':
      row['L4Ci'] = item.attrib['N']
      tag_type = 'L4Title'
  
   if item.tag == 'HEAD':
      if tag_type is not None:
         row[tag_type] = item.text.strip()
 
   if item.tag == 'P':
      row['P'] = item.text.strip()
      rows.append(row.copy())

你可以创建一个dataframe:df = pd.DataFrame(rows)
| L2Ci| L2标题|L3Ci| L3标题|L4Ci| L4标题|L5Ci| L5标题|L6Ci| L 6标题|P|
| --------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|--------------|
| | | 1| 1. DIV 7标题1| 1.1| 1.1 DIV 8标题1|||||(1)案文1|
| | | 1| 1. DIV 7标题1| 1.2| 1.2 DIV 8标题2|||||(a)案文1|
| | | 1| 1. DIV 7标题1| 1.2| 1.2 DIV 8标题2|||||㈡案文2|
| | | 1| 1. DIV 7标题1| 1.2| 1.2 DIV 8标题2|||||(2)正文2.1|
| | | 1| 1. DIV 7标题1| 1.3| 1.3 DIV 8标题3|||||(ff)案文1|
| A|子部分A:DIV 6标题1| 2| 2 DIV 7标题2| 2.1| 2.1 DIV 8标题1|||||(a)案文1|
| A|子部分A:DIV 6标题1| 2| 2 DIV 7标题2| 2.1| 2.1 DIV 8标题1|||||(B)案文2|
| A|子部分A:DIV 6标题1| 2| 2 DIV 7标题2| 2.1| 2.1 DIV 8标题1|||||(c)案文3|
| A|子部分A:DIV 6标题1| 2| 2 DIV 7标题2| 2.2| 2.2 DIV 8标题2|||||(o)文本|
| A|子部分A:DIV 6标题1| 3| 3.第7分部标题3| 3.1| 3.1 DIV 8标题1|||||(r)案文1|
| A|子部分A:DIV 6标题1| 3| 3.第7分部标题3| 3.1| 3.1 DIV 8标题1|||||(s)案文2|
| B|子部分B:DIV 6标题2|||十二岁|12.第8分部标题1|||||7(a)案文|
您可以实现逻辑的其余部分,从P文本填充L5-6标记。

相关问题