bugfix> php > 投稿

私はいくつかのhtmlを配列に変換してからjson文字列に変換しようとしています。

私はこのリファレンスに基づいて開発しています:https://www.codeproject.com/Tips/1074174/Simple-Way-to-Convert-HTML-Table-Data-into-PHP-Arr

これは、JSONに変換する基本的なテーブル/ htmlです。

<table class="table-list table table-responsive table-striped">
<thead>
    <tr>
        <th class="coll-1 name">name</th>
        <th class="coll-2">height</th>
        <th class="coll-3">weight</th>
        <th class="coll-date">date</th>
        <th class="coll-4"><span class="info">info</span></th>
        <th class="coll-5">country</th>
    </tr>
</thead>
<tbody>
<tr>
    <td class="coll-1 name">
        <a href="/username/Jhon Doe/" class="icon"><i class="flaticon-user"></i></a>
        <a href="/username/Jhon Doe/">Jhon Doe</a>
    </td>
    <td class="coll-2 height">45</td>
    <td class="coll-3 weight">50</td>
    <td class="coll-date">9am May. 16th</td>
    <td class="coll-4 size mob-info">abcd</td>
    <td class="coll-5 country"><a href="/country/CA/">CA</a></td>
</tr>
<tr>
    <td class="coll-1 name">
        <a href="/username/Kasim Shk/" class="icon"><i class="flaticon-user"></i></a>
        <a href="/username/Kasim Shk/">Kasim Shk</a>
    </td>
    <td class="coll-2 height">33</td>
    <td class="coll-3 weight">54</td>
    <td class="coll-date">Mar. 14th '18</td>
    <td class="coll-4 size mob-info">ijkl</td>
    <td class="coll-5 country"><a href="/country/UAE/">UAE</a></td>
</tr>
</tbody>
</table>


次のようなJSON出力が必要です。

[
    {   
        "user_link": "/username/Jhon Doe/",
        "name": "Jhon Doe",
        "height": "45",
        "weight": "50",
        "date": "Apr. 01st '18",
        "info": "abcd",
        "country": "CA"
    },
    {   
        "user_link": "/username/Kasim Shk/",
        "name": "Kasim Shk",
        "height": "33",
        "weight": "54",
        "date": "Mar. 14th '18",
        "info": "ijkl",
        "country": "UAE"
    }
]


これは私がPHPで試していたことです:(

ただし、これはユーザーのリンクを取得できず、名前がJSONで適切ではありません。

(上記と同じHTMLテーブル@http://rudraproduction.in/htmltable.php)

header("Access-Control-Allow-Origin: *");                                                                            
header('Content-Type: application/json');
error_reporting(E_ERROR | E_PARSE);
$time_start = microtime(true);
$All = [];
$link       = 'http://rudraproduction.in/htmltable.php';
$jsonData   = file_get_contents($link);
//echo $jsonData;
$dom = new DOMDocument;
$dom->loadHTML($jsonData);
$tables = $dom->getElementsByTagName('table');
$tr     = $dom->getElementsByTagName('tr'); 
foreach ($tr as $element1) {        
    for ($i = 0; $i < count($element1); $i++) {
        //Not able to fetch the user's link :(
        $link       = $element1->getElementsByTagName('td')->item(0)->getElementsByTagName('a');    // To fetch user link
        $name       = $element1->getElementsByTagName('td')->item(0)->textContent;                  // To fetch name
        $height     = $element1->getElementsByTagName('td')->item(1)->textContent;                  // To fetch height
        $weight     = $element1->getElementsByTagName('td')->item(2)->textContent;                  // To fetch weight
        $date       = $element1->getElementsByTagName('td')->item(3)->textContent;                  // To fetch date
        $info       = $element1->getElementsByTagName('td')->item(4)->textContent;                  // To fetch info
        $country    = $element1->getElementsByTagName('td')->item(5)->textContent;                  // To fetch country
        array_push($All, array(
            "user_link" => $link,
            "name"      => $name,
            "height"    => $height,
            "weight"    => $weight,
            "date"      => $date,
            "info"      => $info,
            "country"   => $country
        ));
    }
}
echo json_encode($All, JSON_PRETTY_PRINT);


PHPコードの出力は次のとおりです。

[
    {
        "user_link": "http:\/\/rudraproduction.in\/htmltable.php",
        "name": null,
        "height": null,
        "weight": null,
        "date": null,
        "info": null,
        "country": null
    },
    {
        "user_link": "http:\/\/rudraproduction.in\/htmltable.php",
        "name": "\r\n\t\t\r\n\t\tJhon Doe\r\n\t",
        "height": "45",
        "weight": "50",
        "date": "9am May. 16th",
        "info": "abcd",
        "country": "CA"
    },
    {
        "user_link": "http:\/\/rudraproduction.in\/htmltable.php",
        "name": "\r\n\t\t\r\n\t\tKasim Shk\r\n\t",
        "height": "33",
        "weight": "54",
        "date": "Mar. 14th '18",
        "info": "ijkl",
        "country": "UAE"
    }
]

回答 1 件
  • 私は XPath を使用することを好みます   DomDocument と  構文のユーティリティ/使いやすさのため。 <tr> のみをターゲットにすることにより   <tbody> 内の要素  タグを使用すると、必要なすべてのデータにアクセスできます。

    href を除く  値、各 <td> の最後の「全文字」部分文字列  クラス値は、関連付けられた値に必要なキーを表します。このために私は preg_match() を使用しています  クラス属性の最後の「単語」を抽出します。

    とき $key  は name です 、 href  属性値はハードコードキー user_link と共に保存する必要があります 。

    サンプルの日付値には、目的の形式を得るための準備が必要です。入力データはさまざまなので、正規表現を変更して strtotime() を許可する必要がある場合があります  日付式を適切に処理します。

    コード:(デモ)

    $html = <<<HTML
    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
    </head>
    <body>
    <table class="table-list table table-responsive table-striped" border="1">
    <thead>
        <tr>
            <th class="coll-1 name">name</th>
            <th class="coll-2">height</th>
            <th class="coll-3">weight</th>
            <th class="coll-date">date</th>
            <th class="coll-4"><span class="info">info</span></th>
            <th class="coll-5">country</th>
        </tr>
    </thead>
    <tbody>
    <tr>
        <td class="coll-1 name">
            <a href="/username/Jhon Doe/" class="icon"><i class="flaticon-user"></i></a>
            <a href="/username/Jhon Doe/">Jhon Doe</a>
        </td>
        <td class="coll-2 height">45</td>
        <td class="coll-3 weight">50</td>
        <td class="coll-date">9am May. 16th</td>
        <td class="coll-4 size mob-info">abcd</td>
        <td class="coll-5 country"><a href="/country/CA/">CA</a></td>
    </tr>
    <tr>
        <td class="coll-1 name">
            <a href="/username/Kasim Shk/" class="icon"><i class="flaticon-user"></i></a>
            <a href="/username/Kasim Shk/">Kasim Shk</a>
        </td>
        <td class="coll-2 height">33</td>
        <td class="coll-3 weight">54</td>
        <td class="coll-date">Mar. 14th '18</td>
        <td class="coll-4 size mob-info">ijkl</td>
        <td class="coll-5 country"><a href="/country/UAE/">UAE</a></td>
    </tr>
    </tbody>
    </table>
    </body>
    </html>
    HTML;
    $dom = new DOMDocument;
    $dom->loadHTML($html);
    $xpath = new DOMXPath($dom);
    foreach ($xpath->query('//tbody/tr') as $tr) {
        $tmp = []; // reset the temporary array so previous entries are removed
        foreach ($xpath->query("td[@class]", $tr) as $td) {
            $key = preg_match('~[a-z]+$~', $td->getAttribute('class'), $out) ? $out[0] : 'no_class';
            if ($key === "name") {
                $tmp['user_link'] = $xpath->query("a[@class = 'icon']", $td)[0]->getAttribute('href');
            }
            $tmp[$key] = trim($td->textContent);
        }
        $tmp['date'] = date("M. dS 'y", strtotime(preg_replace('~\.|\d+[ap]m *~', '', $tmp['date'])));
        $result[] = $tmp;
    }
    var_export($result);
    echo "\n----\n";
    echo json_encode($result);
    
    

    出力:(マルチディメンション配列として、jsonエンコードされた文字列)

    array (
      0 => 
      array (
        'user_link' => '/username/Jhon Doe/',
        'name' => 'Jhon Doe',
        'height' => '45',
        'weight' => '50',
        'date' => 'May. 16th \'18',
        'info' => 'abcd',
        'country' => 'CA',
      ),
      1 => 
      array (
        'user_link' => '/username/Kasim Shk/',
        'name' => 'Kasim Shk',
        'height' => '33',
        'weight' => '54',
        'date' => 'Jan. 01st \'70',
        'info' => 'ijkl',
        'country' => 'UAE',
      ),
    )
    ----
    [{"user_link":"\/username\/Jhon Doe\/","name":"Jhon Doe","height":"45","weight":"50","date":"May. 16th '18","info":"abcd","country":"CA"},{"user_link":"\/username\/Kasim Shk\/","name":"Kasim Shk","height":"33","weight":"54","date":"Jan. 01st '70","info":"ijkl","country":"UAE"}]
    
    

あなたの答え