HTML内の文字列の出現数を数える。

設計書ばかりと睨めっこしていたら、気分が悪くなってきたので、気晴らしにプログラムを書きました。かなり汚いプログラムだけど、さらしておきます。先人たちの知恵も入っているので、参照元を記述したいところですが、かなり昔のプログラムを寄せ集めたので、忘れてしまっています。思い出したら、参照元を記述します。といっても、基本ロジックだけですが。エラー制御とかは、無視しているので、万が一、使用したいという奇特な方は、自己責任でご使用ください。
処理の内容は、urlから、htmlを拾ってきて、mecabを使って名詞をカウントしています。本来なら、html parserとかで、タグを消すのが美しいのだろうけど、適当なライブラリが見つからなかったため、ごっちゃでカウント。

hoge.cpp

#include <string>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <iterator>

#include "curl/curl.h"
#include "mecab.h"

#define CHECK(eval) if (! eval) { \
   const char *e = tagger ? tagger->what() : MeCab::getTaggerError(); \
   std::cerr << "Exception:" << e << std::endl; \
   delete tagger; \
   return -1; }

static std::string buffer;
static int writer(char *data, size_t size, size_t nmemb, std::string *writerData)
{
    int result = 0;
    if (writerData != NULL) {
        buffer->append(data, size * nmemb);
        result = size * nmemb;
    }
    return result;
}
std::string getHtml(const std::string url)
{
    CURL *curl;
    CURLcode result;

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_HEADER, 0);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);

        result = curl_easy_perform(curl);

        curl_easy_cleanup(curl);

        if (result == CURLE_OK)
            return  buffer;
        else
            return NULL;
    }
}
int parse_mecab(const std::string article, std::map<std::string, int>& v)
{
    std::string tmp;
    MeCab::Tagger *tagger = MeCab::createTagger("");
    CHECK(tagger);

    const MeCab::Node* node = tagger->parseToNode(article.c_str());
    CHECK(node);
    for (; node; node = node->next) {
        // 名詞のみ。ただし、記号と、数字は、除外
        if(node->posid >= 36 && node->posid <= 67 &&
           node->posid != 36 && node->posid != 48) {
            tmp = std::string((const char*)node->surface, node->length);
            v[tmp]++;
        }
    }
    delete tagger;
    return 0;
}
bool greater_count(const std::pair<std::string, int>& x, const std::pair<std::string, int>& y) 
{
    return x.second > y.second;
}
int main(int argc, char* argv[]) 
{

    std::map<std::string, int> v;
    if (argc < 1) return -1;

    const std::string html = getHtml(std::string(argv[1]));
    int rc = parse_mecab(html, v);

    std::vector<std::pair<std::string, int> > tmp(v.begin(), v.end());
    std::sort(tmp.begin(), tmp.end(), greater_count);
    std::vector<std::pair<std::string, int> >::iterator i = tmp.begin();

    for (; i != tmp.end(); ++i)
        std::cout << i->first << ":" << i->second << std::endl;

    return 0;
}

コンパイルは、
$ g++ `curl-config --cflags` `mecab-config --cflags` `curl-config --libs` `mecab-config --libs` hoge.cpp
で、どぞ。
使い方は、
$ ./a.out http://www.yahoo.co.jp
;-P