3

問題/質問

解析したいボット情報のデータベースがあります。RFC822 メッセージに似ていると言われています。

車輪を再発明して独自のパーサーを作成する前に、何か他のものが既に利用可能であるかどうかを確認することにしました。私はimap_rfc822_parse_headers()、まさに私が望むことをしているようです。残念ながら、IMAP 拡張機能は私の環境では利用できません。

オンラインや Stack Overflow で多くの代替案を見てきました。残念ながら、それらはすべて電子メール用に構築されており、必要以上のことを行っています... 多くの場合、電子メール全体を解析し、特別な方法でヘッダーを処理します。これらのヘッダーを便利なオブジェクトまたは配列に単純に解析したいだけです。

利用可能なストレートPHPバージョンimap_rfc822_parse_headers()、またはこのようなデータを解析する同等のものはありますか? そうでない場合は、自分で書きます。

サンプルデータ

robot-id: abcdatos
robot-name: ABCdatos BotLink
robot-from: no
robot-useragent: ABCdatos BotLink/1.0.2 (test links)
robot-language: basic
robot-description: This robot is used to verify availability of the ABCdatos
                   directory entries (http://www.abcdatos.com), checking
                   HTTP HEAD. Robot runs twice a week. Under HTTP 5xx
                   error responses or unable to connect, it repeats
                   verification some hours later, verifiying if that was a
                   temporary situation.
robot-history: This robot was developed by ABCdatos team to help
               working in the directory maintenance.
robot-environment: commercial
modified-date: Thu, 29 May 2003 01:00:00 GMT
modified-by: ABCdatos

robot-id:                       acme-spider
robot-name:                     Acme.Spider
robot-cover-url:                http://www.acme.com/java/software/Acme.Spider.html
robot-exclusion:                yes
robot-exclusion-useragent:      Due to a deficiency in Java it's not currently possible to set the User-Agent.
robot-noindex:                  no
robot-host:                     *
robot-language:                 java
robot-description:              A Java utility class for writing your own robots.
robot-history:                  
robot-environment:              
modified-date:                  Wed, 04 Dec 1996 21:30:11 GMT
modified-by:                    Jef Poskanzer

...
4

2 に答える 2

3

$data上記で貼り付けたサンプル データが含まれていると仮定すると、パーサーは次のようになります。

<?php

/* 
 * $data = <<<'DATA'
 * <put-sample-data-here>
 * DATA;
 *
 */

$parsed  = array();
$blocks  = preg_split('/\n\n/', $data);
$lines   = array();
$matches = array();
foreach ($blocks as $i => $block) {
    $parsed[$i] = array();
    $lines = preg_split('/\n(([\w.-]+)\: *((.*\n\s+.+)+|(.*(?:\n))|(.*))?)/',
                        $block, -1, PREG_SPLIT_DELIM_CAPTURE);
    foreach ($lines as $line) {
        if(preg_match('/^\n?([\w.-]+)\: *((.*\n\s+.+)+|(.*(?:\n))|(.*))?$/',
                      $line, $matches)) {
            $parsed[$i][$matches[1]] = preg_replace('/\n +/', ' ',
                                                    trim($matches[2]));
        }
    }
}

print_r($parsed);
于 2012-10-10T08:22:34.070 に答える
1

メッセージの MIME タイプは非常に一般的です。パーサーはたくさんありますが、一般的にググることは困難です。個人的には、形式がある程度一貫している場合は、ここで正規表現に頼っています。

たとえば、次の 2 つでうまくいきます。

  // matches a consecutive RFC821 style key:value list
define("RX_RFC821_BLOCK", b"/(?:^\w[\w.-]*\w:.*\R(?:^[ \t].*\R)*)++\R*/m");

  // break up Key: value lines
define("RX_RFC821_SPLIT", b"/^(\w+(?:[-.]?\w+)*)\s*:\s*(.*\n(?:^[ \t].*\n)*)/m");

1 番目は message/* 行の一貫したブロックを分割し、2 番目はそのような各ブロックを分割するために使用できます。ただし、連続する値の行から先頭のインデントを削除するには、後処理が必要です。

于 2012-10-09T17:40:30.023 に答える