【问题标题】:Dom Traversal with lxml into a graph database and pass on ID to establish a complete treeDom Traversal with lxml进入图数据库并传递ID建立完整树
【发布时间】:2021-10-05 03:21:39
【问题描述】:

我正在将由 DOM 树构成的分层数据插入到图形数据库中,但是我无法在节点之间建立完整的关系。我在循环时最终截断了树木

下面的代码说明了遍历 DOM 节点、插入标签并获取最后插入的 id。我遇到的问题是如何通过传递从上一次迭代中获得的 ID 来正确连接树。 当我使用递归时,我遇到了同样的问题。 如何循环和传递 ID,以便它们可以均匀地连接到所有节点树?

考虑以下 HTML

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8"/>
    <title>Document</title>
  </head>
  <body>
    <ul class="menu">
      <div class="itm">home</div>
      <div class="itm">About us</div>
      <div class="itm">Contact us</div>
    </ul>
    <div id="idone" class="classone">
      <li class="item1">First</li>
      <li class="item2">Second</li>
      <li class="item3">Third</li>
      <div id="innerone"><h1>This Title</h1></div>
      <div id="innertwo"><h2>Subheads</h2></div>      
    </div>
    <div id="second" class="below">
      <div class="inner">
        <h1>welcome</h1>
        <h1>another</h1>
        <h2>third</h2>
      </div>
    </div>
  </body>
</html>

使用当前的 python 代码,我最终得到了如图所示的截断树。我省略了图形数据库驱动程序。为了专注于密码,因为大多数图形数据库都遵循几乎相同的密码查询。

import json
from lxml import etree
from itertools import tee
from lxml import html
for n in dom_tree.iter():
        cursor = Cypher("CREATE (t:node {tag: %s} ) RETURN id(t)", params=(n.tag,))
    
        parent_id = cursor.fetchone()[0]  # get last inserted ID
        ag.commit()
        print(f"Parent:{n.tag}")
        for x in n.iterchildren():
            cursor = Cypher("CREATE (x:node {tag: %s} ) RETURN id(x)", params=(x.tag,))
            xid = cursor.fetchone()[0]  # get last inserted ID
            ag.commit()
            print(f"--------{x.tag}")
            cx = Cypher("MATCH (p:node),(k:node) WHERE id(p) = %s AND id(k) = %s CREATE (p)-[:connect {name: p.name+ '->'+k.name}]->(k)", params=(eid, xid,))
            

【问题讨论】:

    标签: python-3.x xpath neo4j lxml graph-databases


    【解决方案1】:

    在您的情况下,您一次又一次地为父节点创建标记节点,您需要为每个级别向下传递父节点的标识符。

    您必须采用递归方法,将父级的 id 传递给递归调用的函数。

    或者您需要为 dom 树中的元素分配一个 id,例如基于级别和位置(兄弟姐妹)来唯一标识它们。

    在neo4j中你也可以使用

    MATCH (n) WHERE id(n) = $id
    MERGE (n)-[:CHILD]->(m:Node {tag:$tag)
    

    在父级的上下文中创建子级,但这不适用于重复标签。

    我会采用递归方法。

    【讨论】:

    • 你有一些代码sn-ps可以试试吗?
    【解决方案2】:

    ElementTree 提供了一种方法,getiterator(),用于遍历树中的每个元素。

    当您访问每个节点时,您还可以使用element.getchildren() 获取其子节点的列表,或者使用element.getparent() 获取其父节点的列表。

    from lxml import html
    tree = html.parse("about.html")
    for element in tree.getiterator():
        if parent := element.getparent():
            print(f"The element {element.tag} with text {element.text} and attributes {element.attrib} is the child of the element {parent.tag}")
    
    

    【讨论】:

    • 但是如何打印出它们之间的关系呢?
    • 虽然我对 Cypher 不够熟悉,无法将其调整为正确的命令,但我已经编辑了答案以打印元素之间的关系。
    • 请注意,getiterator() 已弃用。它在 lxml 中可用,但不再在 ElementTree 中(在 Python 3.9 中删除)。 lxml.de/api/lxml.etree._Element-class.html#getiterator。 getchildren() 也已弃用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-21
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 1970-01-01
    相关资源
    最近更新 更多