2

我正在试验 ArborJS,试图建立一个知识树。这里是我的测试区(左键进入节点,右键回到开头)。我已经充实了“人文与艺术”部分的“全部”,所以我建议通过该区域进行播放。

我正在从维基百科的学术学科列表文章中构建这棵树。

现在,我从一个 mySQL 表中提取数据(通过 PHP)。表结构为TreeNodeID、ParentID、Title。“TreeNodeID”是主键(自动递增),“ParentID”是节点的父节点,“Title”是应该在节点上显示的文本。

我现在在这篇文章的第 7 页,共 27 页。我觉得我没有利用我的计算机的能力来自动化这个手动输入的过程。

我刚刚制作了所有主题的文本文件。它采用以下格式:

Anthropology
    Biological Anthropology
        Forensic Anthropology
        Gene-Culture Coevolution
        Human Behavioral Ecology
    Anthropological Linguistics
        Synchronic Linguistics
        Diachronic Linguistics
        Ethnolinguistics
        Socioloinguistics
    Cultural Anthropology
        Anthropology of Religion
        Economic Anthropology
Archaelogy
...

如何使用 PHP 来完成此操作并填充我的数据库(为每个节点使用正确的 ParentID)?

更新#3:工作代码(由下面的正确答案给出)

<?php
//echo "Checkpoint 1";

$data = "
Social sciences
    Anthropology
        Biological anthropology
            Forensic anthropology
            Gene-culture coevolution
            Human behavioral ecology
            Human evolution
            Medical anthropology
            Paleoanthropology
            Population genetics
            Primatology
        Anthropological linguistics
            Synchronic linguistics (or Descriptive linguistics)
            Diachronic linguistics (or Historical linguistics)
            Ethnolinguistics
            Sociolinguistics
        Cultural anthropology
            Anthropology of religion
            Economic anthropology
            Ethnography
            Ethnohistory
            Ethnology
            Ethnomusicology
            Folklore
            Mythology
            Political anthropology
            Psychological anthropology
    Archaeology
        ...(goes on for a long time)
";

//echo "Checkpoint 2\n";

$lines = preg_split("/\n/", $data);

$parentids = array(0 => null);
$db = new PDO("host", 'username', 'pass');
$sql = 'INSERT INTO `TreeNode` SET ParentID = ?, Title = ?';
$stmt = $db->prepare($sql);

//echo "Checkpoint 3\n";

foreach ($lines as $line) {
    if (!preg_match('/^([\s]*)(.*)$/', $line, $m)) {
        continue;
    }
    $spaces = strlen($m[1]);
    //$level = intval($spaces / 4); //assumes four spaces per indent
    $level = strlen($m[1]); // if data is tab indented
    $title = $m[2];
    $parentid = ($level > 0 ? $parentids[$level - 1] : 1); //All "roots" are children of "Academia" which has an ID of "1";

    $rv = $stmt->execute(array($parentid, $title));

    $parentids[$level] = $db->lastInsertId();
    echo "inserted $parentid - " . $parentid . " title: " . $title . "\n";
}
?>
4

3 回答 3

1

未经测试,但这应该适合你(使用 PDO):

<?php

$data = "
Anthropology
    Biological Anthropology
        Forensic Anthropology
        Gene-Culture Coevolution
        Human Behavioral Ecology
    Anthropological Linguistics
        Synchronic Linguistics
        Diachronic Linguistics
        Ethnolinguistics
        Socioloinguistics
    Cultural Anthropology
        Anthropology of Religion
        Economic Anthropology
Archaelogy
";

$lines = preg_split("/\n/", $data);

$parentids = array(0 => null);

$sql = 'INSERT INTO `table` SET ParentID = ?, Title = ?';
$stmt = $db->prepare($sql);

foreach ($lines as $line) {
    if (!preg_match('/^([\s]*)(.*)$/', $line, $m)) {
        continue;
    }
    #$spaces = strlen($m[1]);
    #$level = intval($spaces / 4); # if data is space indented
    $level = strlen($m[1]); # assumes data is tab indented
    $title = $m[2];

    $parentid = $level > 0
        ? $parentids[$level - 1]
        null;

    $rv = $stmt->execute(array($parentid, $title));

    $parentids[$level] = $db->lastInsertId();
}
于 2012-09-16T18:57:08.880 回答
0

您可以尝试以下方法

// parser.php

<?php
include_once './vendor/autoload.php';

use Symfony\Component\DomCrawler\Crawler;

$crawler = new Crawler(file_get_contents('http://en.wikipedia.org/wiki/List_of_academic_disciplines'));

$texts = $crawler->filter('.tocnumber + .toctext');
$numbers = $crawler->filter('.tocnumber');


$last = '';

for ($i=0; $i < count($numbers); $i++) {
    $value = $numbers->eq($i)->text();
    if(!preg_match('/\d+.\d+/', $value)) {
        // is a root discipline
        $last = $texts->eq($i)->text();
    } else {
        // is a leaf discipline
        $disciplines[$last][$texts->eq($i)->text()] = $texts->eq($i)->text();
    }
}

var_dump($disciplines);

有了这个,你可以做一些更多的事情,比如持久化数据库或任何内容,并且对其他 DOM 解析任务很有用

我使用了 Symfony Components 的 CssSelector 和 DomCrawler 很容易安装

作曲家.json

{
    "name": "wiki-parser",
    "require": {
        "php": ">=5.3.3",
        "symfony/dom-crawler": "2.1.0",
        "symfony/css-selector": "2.1.0"
    }
}

在控制台中

$ php composer.phar install

看看getcomposer

于 2012-09-16T19:57:14.893 回答
0

我会说首先复制粘贴到文本文件更容易,就像您在上面所做的那样缩进。然后解析它:

  • 读取每一行(一次一行),为您提供节点文本。
  • 每个缩进都是一个新的孩子,所以前一个节点是父 id
  • \t如果您一直保持一致或保持计数,请检查 dents-count indent level。注意 0 缩进(根)。

这将允许您构建一个包含每个学科的关联数组。然后你解释它。例如:

  • 获取所有根节点(根节点的第一个子节点,视情况而定)并给它们一个增量 id parse_id
  • 从上面继续沿着数组,将parse_ids 分配给所有节点。
  • 然后开始将这些数据放入 MySQL。正如你所做的那样,将mysqli_insert_id数组与 一起添加,例如parse_id调用。db_id这应该用于parent_id将 db 中的 required 与 parent 的parse_id.

假设您不尝试检查常见研究或唯一节点文本,那应该足够简单。

于 2012-09-16T18:49:48.053 回答