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