【PHP】じぶんコインで発行されてる全コインIDを取得してみた

お試しする場合は記事を最後まで読んでからにしてください!!

全コインIDがほしい

じぶんコインのAPIで遊んでたら発行されてるコインIDの一覧がほしくなりました。でもそんなAPI提供されてないし、どうしよう?ってことで、無いなら作ればいいじゃないって考えで始めてしまいました。最初JavaScriptで作ってましたが今後のことを考えるとサーバーサイドで動作した方がいいなぁと思ったのでPHPでも作ってみたいと思います。

方法を検討

多分方法はいくつかあると思いますが、私はランキングページのHTMLを全部読み取って必要な部分だけ抽出するって方法で実現したいと思います。この方法をスクレイピングっていうそうです。かっこいいですね。

phpQuery

PHPでスクレイピングするphpQueryっていうライブラリが提供されてるので使ってみましょう。リンクから[phpQuery-0.9.5.386-onefile.zip]をダウンロードしてみました。

phpQueryをダウンロード

テスト環境

■現在のテスト環境
MANP 5.2
WordPress 5.0
PHP 7.2.10
phpQuery-0.9.5.386
MySQL

■テストソース
・今回もテスト用リンクの設置に使います。
/Applications/MANP/htdocs/phptest/index.html
・動作確認用のソース
/Applications/MANP/htdocs/phptest/phpquery/phpqueryTest.php
/Applications/MANP/htdocs/phptest/phpquery/testTable.html
・ID取得用のソース(今回の主役)
/Applications/MANP/htdocs/phptest/phpquery/allCoinID.php
・さっきダウンロードしてきたライブラリ(更新日付みたら2009年、、、)
/Applications/MANP/htdocs/phptest/phpquery/phpQuery-onefile.php

動作確認

まずはいつも通りindex.htmlにテスト用リンクを作成しておきます。

<html>
    <head>
        <title>PHP Test</title>
    </head>
    <body>
        <a href="./helloworld.php">Hello World</a><br>
        <a href="./coinCount.php">coinCount</a><br>
        <a href="./coinMax.php">coinMax</a><br>
        <a href="./coinPer.php">coinPer</a><br>
        <a href="./coinValue.php">coinValue</a><br>
        <a href="./bending.php">bending</a><br>
        <a href="./coinInfo.php">coinInfo</a><br>
        <!--以下が今回追加したテストリンク-->
<a href="./phpquery/phpqueryTest.php">phpqueryTest</a><br> <a href="./phpquery/allCoinID.php">allCoinID</a><br> </body> </html>

phpQuery.phpがちゃんと使えるかテストしてみましょう。動作確認用ソースはこちら。

<html>
    <head>
        <title>phpqueryTest</title>
    </head>
    <body>
    <?php
        require_once("./phpQuery-onefile.php");
        //じぶんコインのメインページから情報取得(ログイン済みの状態)
        $src = file_get_contents("https://crypto-app.tokyo/qCoin/?m=ganbarumasu0525");
        //<p>タグのテキストを取得
        echo phpQuery::newDocument($src)->find("p")->text();
    ?>
    </body>
</html>

正常に取得できてるみたいです。これで準備完了ですね。

コインID取得への道

多分全IDを取得するのに適したページは今の所ランキングページかなと思います。(それ以外に全IDを確認できそうなページはなさそう)。ということでランキングページのソースコードを眺めてみることに。 ふむふむ、リンクの中にIDがありそうですね。

それでは、hrefの中身を取得する方法を試してみたいと思います。phpqueryをダウンロードしたところにwikiがありますね。これをみながら、、、、英語かぁよくわからんなぁ。なんかどのページのリンク踏んでもjQueryのページにつながってるなぁ。使い方はjQueryに準拠してるんだろうか。。。てかそもそもjQueryってなんなの?

jQueryとは?

wiki引用

jQuery(ジェイクエリー)は、ウェブブラウザ用のJavaScriptコードをより容易に記述できるようにするために設計されたJavaScriptライブラリである。

もしかして

phpQueryってjQueryのPHP版みたいなもんなのかな?記述方法もjQueryに則ってるっぽいのでjQueryの公式ページみながら記述を確認するのが正しいのかもなぁ。試しながら確認してみよ。

テーブルの構造確認

見た目こんな感じ

ソースコード抜粋

<tr>
    <td>
        <a href="/qCoin/?m=ganbarumasu0525">
            <img src="imgCache/ganbarumasu0525.gif?1535506643">
        </a>
        <p>持って<br>る
        </p>
    </td>
    <td>25位 
        <a href="/qCoin/?m=ganbarumasu0525">がんばる
        </a><br>
        エアドロ<b>83508</b>枚くらい
        <hr>
        <span>頑張ってブログ運営することにしました\(^o^)/https://www.ganbaru.lifeが..
        </span> 
        <hr>
        <a href="/qCoin/?m=ganbarumasu0525#info">このコインで買える価値
        </a>|
        <a href="/qCoin/?m=ganbarumasu0525#airdrop">エアドロで応援してGET
        </a>
    </td>
</tr>

styleなどの今回は不要だと思うオプションについては省略しました。ランキングはこのテーブルの形で出力されているようです。

抽出条件の検討

単純に考えると<table> -> <tr> を辿って最初の<td> -> <a href>から要素を抜き出す感じかな?まぁ試しながらコマンドに落とし込んでみましょう。何度もテストで接続するのもアクセス負荷的にやばい気もするのでテスト用のテーブルを作成してみました。

こんな感じ。このテストテーブルをローカルにおいて検証していきましょう。これだったら迷惑かからないですね。画像とかは参照できないですがまぁ今回はこのままで。styleも無視しました。

testTable.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8"/>
        <title>PHP Test</title>
    </head>
    <body>
        <table>
            <tr>
                <td>
                    <a href="/qCoin/?m=ganbarumasu0525">
                        <img src="imgCache/ganbarumasu0525.gif?1535506643">
                    </a>
                    <p>持って<br>る
                    </p>
                </td>
                <td>25位 
                    <a href="/qCoin/?m=ganbarumasu0525">がんばる
                    </a><br>
                    エアドロ<b>83508</b>枚くらい
                    <hr>
                    <span>頑張ってブログ運営することにしました\(^o^)/https://www.ganbaru.lifeが..
                    </span> 
                    <hr>
                    <a href="/qCoin/?m=ganbarumasu0525#info">このコインで買える価値
                    </a>|
                    <a href="/qCoin/?m=ganbarumasu0525#airdrop">エアドロで応援してGET
                    </a>
                </td>
            </tr>
        </table>
    </body>
</html>

allCoinID.phpもテストソースを参照するように修正しておきます。

//じぶんコインのランキングページを取得(多分ログインしてなくてもいけるはずですが検証ではログインした状態で取得)
//$src = file_get_contents("https://crypto-app.tokyo/qCoin/users.php?m=ganbarumasu0525&page=".$page."&airdropAmount=1");
//testソース読み込み
$src = file_get_contents("./testTable.html");

何も考えずにコマンドにするとこんな感じかなぁ

echo $doc["table:eq(0) tr"]->find("td:eq(0) a")->attr("href");

うんうん、こんな感じ。簡単ですね。早速できましたね。抽出した文字列で「/qCoin/?m=」が不要なのでリプレース関数か何かで削除してみましょう。

おぉ!思った値が取得できた!

$coinID = $doc["table:eq(0) tr"]->find("td:eq(0) a")->attr("href");
 echo str_replace("/qCoin/?m=","",$coinID);

ではテストテーブルをもう少し大きくして試してみましょう!ソースコードは冗長になるので貼り付けませんが見た目はこんな風。

テーブルが長くなったのでforeach文でまわしてみます。これもいけました!!やったね^^(わかりやすいようにIDは変えてます)

foreach($doc["table:eq(0) tr"] as $coinID)
{
    $c = pq($coinID)->find("td:eq(0) a")->attr("href");
    echo str_replace("/qCoin/?m=","",$c)."<br>";
}

このまま一気にいっちゃいましょう!

本番サイトのテーブルは2番目みたいなのでそこだけ修正して実行!!おぉぉおぉおぉとれて、、、、?なんか変な空白があるなぁ。もしや広告枠????それは除外しなきゃなぁ

修正しました!これでどうだ!いけたぁあああ〜

<html>
    <head>
        <title>allCoinID</title>
    </head>
    <body>
    <?php
        require_once("./phpQuery-onefile.php");
        //ページ番号
        $page = 1;
        //じぶんコインのランキングページを取得(多分ログインしてなくてもいけるはずですが検証ではログインした状態で取得)
        $src = file_get_contents("https://crypto-app.tokyo/qCoin/users.php?m=ganbarumasu0525&page=".$page."&airdropAmount=1");
        //testソース読み込み
        //$src = file_get_contents("./testTable.html");
        $doc = phpQuery::newDocument($src);
        foreach($doc["table:eq(1) tr"] as $coinID)
        {
            $c = pq($coinID)->find("td:eq(0) a")->attr("href");
            if($c != null){
                echo str_replace("/qCoin/?m=","",$c)."<br>";
            }
        }
    ?>
    </body>
</html>

ページもめくってみましょう

ページの変数用意してましたが結局ループで使ってる変数と同じ値になるので$pageは削除して$iに変更しました。それでは愚直にまわしてみましょう!現在160ページくらいあるのでとりあえず固定値でついでに処理速度も測ってみます。

<html>
    <head>
        <title>allCoinID</title>
    </head>
    <body>
    <?php
        //処理速度も測ってみます。
        $time_start = microtime(true);
        require_once("./phpQuery-onefile.php");
        for($i = 1; $i <=160; $i++){
            //じぶんコインのランキングページを取得(多分ログインしてなくてもいけるはずですが検証ではログインした状態で取得)
            $src = file_get_contents("https://crypto-app.tokyo/qCoin/users.php?m=ganbarumasu0525&page=".$i."&airdropAmount=1");
            //testソース読み込み
            //$src = file_get_contents("./testTable.html");
            $doc = phpQuery::newDocument($src);
            foreach($doc["table:eq(1) tr"] as $coinID)
            {
                $c = pq($coinID)->find("td:eq(0) a")->attr("href");
                if($c != null){
                    echo str_replace("/qCoin/?m=","",$c)."<br>";
                }
            }
        }
        $time = microtime(true) - $time_start;
        echo "{$time} 秒";
    ?>
    </body>
</html>

とれました!!!!!けど処理時間1115秒って、、、、(約18分)おせぇえええええ。回線速度にも問題がありそう、電車の中だと不安定すぎる。てかこれ相手先に負荷かけてね?大丈夫かなぁ;

俺たちの戦いはこれからだ

昨日こんなツイートが。。。。いや、phpqueryを使えるようになったことは無駄じゃ無いはずだ、、、、

APIを使って取得してみました

はや!!!!!2秒!!!(一行ずつecho使わなければもっと速い!)これが最強でした。。。。次回は取得したIDを使って遊びますw

<html>
    <head>
        <title>allCoinID</title>
    </head>
    <body>
    <?php
        //処理速度も測ってみます。
        $time_start = microtime(true);
        $url = "https://crypto-app.tokyo/qCoin/api/api.php?type=allID";
            
        //cURLのセッション初期化
        $ch = curl_init();

        // オプションを設定(コメントはPHPのリファレンスから引用)
        // 取得する URL 。curl_init() でセッションを 初期化する際に指定することも可能です。
        curl_setopt($ch, CURLOPT_URL, $url); 
        // TRUE を設定すると、curl_exec() の返り値を 文字列で返します。通常はデータを直接出力します。
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //FALSE を設定すると、cURL はサーバー証明書の検証を行いません。 別の証明書を CURLOPT_CAINFO オプションで 指定するか、CURLOPT_CAPATH オプションで 証明ディレクトリを指定します。
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
        
        //改行区切りで分割
        $allID = explode("\n",curl_exec($ch));

        //test
        //$allID = null;
        
        if(!($allID === null)){
            //全出力
            foreach ($allID as &$a) {
                echo $a."<br>";
            }
        }else{
            echo "<p>なんか値がちゃんと取得できてねぇっす!</p>";
        }

        $time = microtime(true) - $time_start;
        echo "{$time} 秒";
    ?>
    </body>
</html>

コメント