node.js スクレイピング cheerio-httpcli の使い方

2014年5月6日更新 view: 475 view
photoBy: http://upload.wikimedia.org/wikipedia/commons/b/b…

cheerio-httpcliってなによ?

http://qiita.com/ujiro99@github/items/648a9400e8b25d717b1e

に書いてあるように、普通のcherrioでスクレイピングすると文字化けする時がある。

スポンサードリンク

だから

{Iconv}  = require "iconv"

{Buffer} = require "buffer"

を使って・・・文字化けしないように・・とあるが

めんどうくさい。

そんな処理を一発でやってくれるのが cheerio-httpcli

https://github.com/ktty1220/cheerio-httpcli

見ればわかると思うが、

  • ファイルを取得
  • 文字化けがあれば文字コードを utf-8 に修正し取得

の2つの事を同時にやってくれる優れもの。

早速コード。

headerを変えることによって、useragent などを偽装することができます。

var request = require('request');
var client = require('cheerio-httpcli');

client.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36';
client.fetch('http://www.ugtop.com/spill.shtml', { q: 'node.js'}, function (err, $, res) {
    // レスポンスヘッダを参照
// console.log(res.headers);

    // HTMLタイトルを表示
    //console.log($('title').text());

    console.log($('body').text());

});

複数サイトを一括スクレイピング

エラー分岐を必ずすること。
でないと意味不明なエラーで止まる。

result[i]にはurlが入っているという前提で。

var client = require('cheerio-httpcli');
for (var i = 0; i < result.length; i++){

           client.fetch(result[i].url,function (err, $, res) {

                if(!err){
                    console.log($("title").text());

                    var keyword = '';
                    var description = '';
                    if ($("meta[name=description]").attr("content")) {
                        description = $("meta[name=description]").attr("content");
                        console.log(description);
                    }

                    if ($("meta[name=keyword]").attr("content")) {
                        keyword = $("meta[name=keyword]").attr("content");
                        console.log(keyword);
                    }

                } else {
                    console.log('エラーが出たがね');

                }

            });


      }

完成版

  • 複数URLをDBから取得
  • 取得したら取得した順番に一気に解析し、指定したIDでDBに保存
  • エラーだったらエラーフラグを立てて保存
connection.query('SELECT * FROM `qjiin_jobtalks` WHERE `url` != \'\' AND `keyword_description_flag` = 0 ORDER BY id desc LIMIT 1').success(function(result){


    for (var i = 0; i < result.length; i++){

        var tmp_result = result[i];

        client.fetch(tmp_result.url,{oribot : tmp_result.id},function (err, $, response) {


            if(!err){
                //キュレーション先のurlを取得
                url = response.req.res.request.uri.href;

                
                tmp_id = url.split('=');
                id = tmp_id[1];

                res = {
                    id:id,
                    url: url,
                    site_title:'',
                    keywords:'',
                    description:'',
                    keyword_description_flag:'1',
                    modified:now
                };



                    if ($("title").text()) {
                        res['site_title'] = $("title").text();
                    }

                    if ($("meta[name=description]").attr("content")) {
                        res['description'] = $("meta[name=description]").attr("content");
                    }

                    if ($("meta[name=keywords]").attr("content")) {

                        res['keywords'] = $("meta[name=keywords]").attr("content");
                    }



                tmbDB.update(res,//更新内容
                    { id: id}//対象
                )
                .error(function (err) {
                    //エラー時の処理
                })
                .success(function (result) {
                 logger.info(id + ' ' + res['site_title']);
                });





         // console.log(res);



        } else {

                //idを取得
                id = err.param.oribot;

                res = {
                    id: id,
                    keyword_description_flag:'1'
                };

                tmbDB.update(res,//更新内容
                    { id: id}//対象
                )
                .success(function (result) {
                 logger.info(id + ' ファイルを取得できなかったもしくは文字コードがおかしいのでエラー処理します');
                });

        }

        });
        

    }

非同期なのに、for文を使うと、 client.fetchの中でtmp_result.id がうまく取得できないので、
一度サーバーにidごと送信し、帰ってきたデータからidを抜き出す。

非同期で一気に取得できるのに、わざわざ1URLずつパクってきても意味ないからね。

coffeescript で書いた場合

request = require('request')
client = require('cheerio-httpcli')


class Dog

constructor: (@name) ->
    @foo = "hoge"
tweet: ->
    console.log "Wan!"
sleep: ->

    client.fetch "http://www.yahoo.co.jp",
     oribot: "hoge"#&oribot=hoge
    , (err, $, response) =># => がコツ
     unless err
        console.log(@.foo)#hoge
        console.log($("title").text())#yahoo japan

d = new Dog()
d.sleep()
スポンサードリンク

関連記事

関連カテゴリ

コロ助

web関連の記事や制作系の記事をどんどんまとめていきます。 宜しくお願いします!

ピックアップ

パソコン・ソフトウェア ランキング

10月19日 ( 土 ) にアクセスが多かった記事はこちら!