Php 删除没有HTML的纯文本文件?

Php 删除没有HTML的纯文本文件?,php,screen-scraping,Php,Screen Scraping,我在纯文本文件中有以下数据: 1. Value Location : Value Owner: Value Architect: Value 2. Value Location : Value Owner: Value Architect: Value ... upto 200+ ... 每个段的编号和字值都会更改 现在我需要将这些数据插入MySQL数据库 你有没有关于我如何遍历和刮取它的建议,这样我就可以得到数字旁边文本的值,以及“位置”、“所有者”、“建筑师”的值 似乎

我在纯文本文件中有以下数据:

1.  Value
Location :  Value
Owner:  Value
Architect:  Value

2.  Value
Location :  Value
Owner:  Value
Architect:  Value

... upto 200+ ...
每个段的编号和字值都会更改

现在我需要将这些数据插入MySQL数据库

你有没有关于我如何遍历和刮取它的建议,这样我就可以得到数字旁边文本的值,以及“位置”、“所有者”、“建筑师”的值


似乎很难使用DOM scraping类,因为不存在HTML标记。

如果每个块都有相同的结构,可以使用
file()
函数:

这样,每一行都是数组中的一项,您可以循环遍历它

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.
}

对于与Topener解决方案一致的($i=0;$i),下面是一个示例,如果每个块是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。我没有添加代码来删除第一段中的冒号


祝你好运!

如果数据一直是结构化的,你可以使用
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);
/*注意末尾的换行符*/

$format=这将为您提供所需的内容

$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

}

这将使用一个非常简单的有状态的面向行的解析器。将解析的数据累积到数组()中的每一行。当有消息告诉您在一条新记录上时,您将转储解析的数据并再次继续

面向行的解析器有一个很好的特性:它们只需要很少的内存,最重要的是需要恒定的内存。它们可以毫不费力地处理千兆字节的数据。我正在管理一堆生产服务器,没有什么比那些脚本将整个文件存储到内存中更糟糕的了(然后用解析的内容填充数组,这需要两倍于原始文件大小的内存)

这是有效的,而且基本上是牢不可破的:

<?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);
?>

一个简单的while就足够了。当然,在for和after语句中应该有sql查询来插入data@Aurelio:不一定……我总是喜欢先写入tab delim或类似文件,然后使用数据库的大容量加载工具(sqlldr、mysql的LOAD DATA Inflie等。它让您有机会在插入之前检查解析。@Joe也是一个很好的解决方案,但Topener既不编写我的解决方案,也不编写您的解决方案。使用他的for,每次都会覆盖相同的变量。这就是我的评论。@Aurelio:事实上,它不会覆盖--这是一个不断增长的数组y、 不过,正如zerodeux所提到的,不构建数组并在每次循环迭代中转储(甚至最好不要在整个文件中发出咕噜声)会更节省内存+1用于面向行的解析,加上许多人会更喜欢fscanf样式,而不是我在自己的评论中提出的正则表达式。我的解决方案对空格和报告行级错误更为健壮,但它的代码量是原来的两倍。+1用于
fscanf
。我不知道这个函数,它看起来非常有用。你怎么知道如果这些值包含空格和其他字符,则可以执行此操作?例如
“这就是(值)!”
。如果值遵循常量结构,只需相应地修改格式字符串。但它可能会变得混乱。如果值变化很大,我建议您使用其他一些解决方案,例如。我编辑了我的注释,以强调面向流/行的解析器。PHP文化是so file()/file\u get\u contents()面向,但这不可缩放。而且您经常希望缩放,特别是在像这样的数据导入问题上。一次吃掉一条记录!
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])
    );

}
<?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);
?>