質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • Node.js

    1993questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

複数のWEBページの情報を取得してくるクローラを作りたい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 272

kaitotokai

score 43

複数のWEBページの情報を取得してくるクローラを作りたい。
http://liginc.co.jp/programmer/archives/4848 を見ながらクローリングのためのコードを書いている。

// Initialize instance
var sequelize = require('sequelize');

// Connect to database
var connection = new sequelize('データベース名', 'ユーザ名', 'パスワード', {オプション: '値'});

// Define models
var sites = connection.define('sites', {
    url: sequelize.TEXT,
    title: sequelize.STRING
});

//Initialize instance
var request = require("request");
var cheerio = require("cheerio");

// Define request url
var requestUrl = "http://www.google.com";

// Send http request
request({url: requestUrl}, function(error, response, body) {
    // If request succeed
    if (!error && response.statusCode == 200) {
        $ = cheerio.load(body); // Create cheerio instance

        // Get response data
        var url = response.request.href;
        var title = $("title").text();

        console.log(url);
        console.log(title);

        // Create new instance
        var site = sites.build();

        // Set fields
        site.url = url;
        site.title = title;

        // Save to database
        site.save()
            .success(function(anotherTask) {
                console.log('Succeed');
            })
            .error(function(error) {
                console.log(error);
            });
    }

    // If error occured
    else {
        console.log("--------------------------------------------------");
        if (error && "code" in error) {
            console.log("Error Code:" + error.code);
        }
        if (error && "errno" in error) {
            console.log("Error No:" + error.errno);
        }
        if (error && "syscall" in error) {
            console.log("Error Syscall:" + error.syscall);
        }
        if (response && "statusCode" in response) {
            console.log("Status Code:" +  response.statusCode);
        }
    }
});


と書いてある中に、

var requestUrl = "http://www.google.com";


とURLが書いてあるが、
複数のWEBページの情報を取得してくるクローラを作りたい場合にはどうしたら良いか?
例えば、nifty ( https://www.nifty.com/ )やlivedoor( http://www.livedoor.com/ )のサイトからもタイトルを取得してきてその情報をDBに入れるようにしたい。しかし、googleとniftyとlivedoorのwebのhtml構造は違う。
質問したい点は、
・取得してきたいWEBページの個数分スクリプトを作った方がいいのか?
・複数のURLをクローリングしたい場合、効率的にクローリングする方法はあるのか?
という点である。
ちなみに、1日1回指定のURLからクロールしたい。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

クローラでもクローリングでもなくスクレイピングですね?

当然サイトの数だけ「どこを取り出すか」の情報が必要で、
サイトの数だけアクセスする必要があります。
しかしハードコーディングしてしまうと対象サイトに変更があるたびに、
コードを書き直す必要がありますし、サイトの数だけスクリプトを作るのもスマートではありません。

私の場合は「どこを取り出してどう処理するか」を別に簡単なスクリプト的ファイルにして、
そのファイルを読み出して処理をするプログラムを書いて使っています。
(VBAで書いてるので参考部分を出せませんが。)

スクリプト的なものを考えなくとも、
Node.jsであればevalでクローリング部分だけ書いたファイルを読むとかって手もありますね。

効率的にクローリングというのは、CPU効率であったり総処理時間の話でしょうか?
サイトの件数分マルチスレッドで並列処理するのが高速でしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/12 23:54

    ありがとうございます。とても参考になります。「どこを取り出してどう処理するか」を別に簡単なスクリプト的ファイルにして、と書かれたのに1点質問があります。サイトの数だけどこを取り出してどう処理するかのメソッドを作りそのメソッドたちを1つのスクリプトにまとめ、それらのメソッドを別のファイルで呼び出してくる、と言う意味でしょうか?

    キャンセル

  • 2018/06/13 02:34

    えーと、私の場合ですが、
    思いっきり独自仕様ですので参考になるかどうかですが、設定ファイル内に、

    [001]
    000=サイト名 // 識別用サイト名
    001=0 // ログインフォームの番号
    002=3 // ログインフォームのIDのinputボックスの番号
    003=4 // ログインフォームの PW inputボックスの番号の番号
    004=6 // ログインサブミットボタンの番号
    005=https://xxx.xxx.xxx/login.php // ログインURL
    006=https://xxx.xxx.xxx/logout.php // ログアウトURL
    007=https://xxx.xxx.xxx/view.php?p=001 // データをゲットするURL=データをゲットするURL
    008=ID // ID
    009=PW // PW
    010=data001,TABLE,1,TR,1,TD,1 // 取り出しデータ位置
    011=data002,TABLE,1,TR,1,TD,2 // 取り出しデータ位置
    012=data003,TABLE,1,TR,2,TD,1 // 取り出しデータ位置
    013=data004,TABLE,1,TR,2,TD,2 // 取り出しデータ位置
    999=Logout,Login(001,002,003,004,008,009),Dataget(010-013),Logout


    という感じのが複数記載してありまして…
    なくなるまで順次読み出し処理をしてます、
    全部変数に読み出した上でスクリプトに書いてある処理のルーチンを順番に回す感じですね。
    どんな感じに設計するかはこの設定ファイルの記載の楽さと高性能さに関わってくるので、
    センス次第ではありますよね。
    JSON形式とかつかっちゃうと手書きが困難になるのであんまりおすすめできないかな。

    自分専用でかつ安全なサーバーで動かすのであれば単純に

    var connection = new sequelize('データベース名', 'ユーザ名', 'パスワード', {オプション: '値'});
    // Define models
    var sites = connection.define('sites', {
    url: sequelize.TEXT,
    title: sequelize.STRING
    });
    //Initialize instance
    var request = require("request");
    var cheerio = require("cheerio");
    .....

    とか書いて読み出してevalするのもアリかと。

    キャンセル

  • 2018/06/13 21:25

    ありがとうございます!!勉強になりました!

    キャンセル

0

Octoparseというスクレイピングツールを使っています。

複数のWEBページの情報を取得するチュートリアルもあります。
http://jp.octoparse.com/tutorial/extract-multiple-pages-through-pagination/

1日1回のクローリングもできます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Node.js

    1993questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。