我在纯文本文件中有以下数据:
1. Value
Location : Value
Owner: Value
Architect: Value
2. Value
Location : Value
Owner: Value
Architect: Value
... upto 200+ ...
每个细分的编号和单词值会发生变化。
现在我需要将这些数据插入到MySQL数据库中。
您是否有关于我如何遍历和抓取它的建议,以便我可以获得数字旁边的文本值以及“位置”,“所有者”,“架构师”的价值?
似乎很难处理DOM抓取类,因为没有HTML标记。
答案 0 :(得分:5)
如果数据经常结构化,您可以使用fscanf
从文件中扫描它们。
/* Notice the newlines at the end! */
$format = <<<FORMAT
%d. %s
Location : %s
Owner: %s
Arcihtect: %s
FORMAT;
$file = fopen('file.txt', 'r');
while ($data = fscanf($file, $format)) {
list($number, $title, $location, $owner, $architect) = $data;
// Insert the data to database here
}
fclose($file);
有关fscanf
in docs的更多信息。
答案 1 :(得分:4)
如果每个块具有相同的结构,您可以使用file()
函数执行此操作:http://nl.php.net/manual/en/function.file.php
$data = file('path/to/file.txt');
这样,每一行都是数组中的一个项目,你可以遍历它。
for ($i = 0; $i<count($data); $i+=5){
$valuerow = $data[$i];
$locationrow = $data[$i+1];
$ownerrow = $data[$i+2];
$architectrow = $data[$i+3];
// strip the data you don't want here, and instert it into the database.
}
答案 2 :(得分:3)
这将适用于一个非常简单的有状态的面向行的解析器。累积的每一行都将数据解析为数组()。当某些东西告诉你正在使用新记录时,你会转储你解析的内容并重新开始。
面向行的解析器有一个很好的属性:它们需要很少的内存和最重要的,恒定的内存。他们可以毫不费力地处理千兆字节的数据。我正在管理一堆生产服务器,没有什么比那些将整个文件插入内存的脚本更糟糕了(然后填充带有解析内容的数组,这需要原始文件大小超过内存的两倍)。
这种方法很有效,而且几乎不会破碎:
<?php
$in_name = 'in.txt';
$in = fopen($in_name, 'r') or die();
function dump_record($r) {
print_r($r);
}
$current = array();
while ($line = fgets($in)) {
/* Skip empty lines (any number of whitespaces is 'empty' */
if (preg_match('/^\s*$/', $line)) continue;
/* Search for '123. <value> ' stanzas */
if (preg_match('/^(\d+)\.\s+(.*)\s*$/', $line, $start)) {
/* If we already parsed a record, this is the time to dump it */
if (!empty($current)) dump_record($current);
/* Let's start the new record */
$current = array( 'id' => $start[1] );
}
else if (preg_match('/^(.*):\s+(.*)\s*/', $line, $keyval)) {
/* Otherwise parse a plain 'key: value' stanza */
$current[ $keyval[1] ] = $keyval[2];
}
else {
error_log("parsing error: '$line'");
}
}
/* Don't forget to dump the last parsed record, situation
* we only detect at EOF (end of file) */
if (!empty($current)) dump_record($current);
fclose($in);
?>
在function dump_record
中,你需要一些适合自己口味的东西,比如打印一个正确格式化的INSERT SQL语句。
答案 3 :(得分:2)
这会给你你想要的东西,
$array = explode("\n\n", $txt);
foreach($array as $key=>$value) {
$id_pattern = '#'.($key+1).'. (.*?)\n#';
preg_match($id_pattern, $value, $id);
$location_pattern = '#Location \: (.*?)\n#';
preg_match($location_pattern, $value, $location);
$owner_pattern = '#Owner\: (.*?)\n#';
preg_match($owner_pattern, $value, $owner);
$architect_pattern = '#Architect\: (.*?)#';
preg_match($architect_pattern, $value, $architect);
$id = $id[1];
$location = $location[1];
$owner = $owner[1];
$architect = $architect[1];
mysql_query("INSERT INTO table (id, location, owner, architect) VALUES ('".$id."', '".$location."', '".$owner."', '".$architect."')");
//Change MYSQL query
}
答案 4 :(得分:0)
同意Topener解决方案,这是一个例子,如果每个块是4行+空行:
$data = file('path/to/file.txt');
$id = 0;
$parsedData = array();
foreach ($data as $n => $row) {
if (($n % 5) == 0) $id = (int) $row[0];
else {
$parsedData[$id][$row[0]] = $row[1];
}
}
结构将方便使用,对于MySQL或whatelse。我没有添加代码来删除第一段中的冒号。
祝你好运!答案 5 :(得分:0)
preg_match_all("/(\d+)\.(.*?)\sLocation\s*\:\s*(.*?)\sOwner\s*\:\s*(.*?)\sArchitect\s*\:\s*(.*?)\s?/i",$txt,$m);
$matched = array();
foreach($m[1] as $k => $v) {
$matched[$v] = array(
"location" => trim($m[2][$v]),
"owner" => trim($m[3][$v]),
"architect" => trim($m[4][$v])
);
}