Googleニュースで指定した単語を検索して、ヒット数を返すサンプル

明日はゆっくり出社予定のbonlifeです。id:eliya:20080113:1200259537 を読んで、Pythonの練習として、少し修正したものを書いてみました。Python使う人が増えると(めぐりめぐって私にとって必要なPython情報が簡単に手に入るようになって)良いなぁ、とか思いつつ ;-p

  • 実行例
> countgooglenews.py
--------------------------------------------------------------------------------
Keyword        : google
Number of hits : 1
URL            : http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=h&as_drrb=q&q=google
Target period  : h
--------------------------------------------------------------------------------
Keyword        : google
Number of hits : 723
URL            : http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=d&as_drrb=q&q=google
Target period  : d
--------------------------------------------------------------------------------
Keyword        : google
Number of hits : 713
URL            : http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=w&as_drrb=q&q=google
Target period  : w
--------------------------------------------------------------------------------
Keyword        : google
Number of hits : 649
URL            : http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=m&as_drrb=q&q=google
Target period  : m

検索結果の数はあまり当てにならないみたいですね…。1日の検索結果の方が1週間より多かったり、1週間の検索結果の方が以下略だったり。"約"ってことだし、まぁ、良いか。(検索の仕方が間違ってたらご指摘プリーズです。)

  • 実行例 (関数を読み込んで実行)
In [1]: from countgooglenews import count_google_news

In [2]: count_google_news('Python')
Out[2]:
{'count': 26,
 'keyword': 'Python',
 'target_period': 'm',
 'url': 'http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=m&as_drrb=q&q=Python'}

In [3]: count_google_news('Python','h')
Out[3]:
{'count': 0,
 'keyword': 'Python',
 'target_period': 'h',
 'url': 'http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=h&as_drrb=q&q=Python'}


In [4]: for i in ['Python', 'Ruby', 'Perl', 'Java']:
   ...:     count_google_news(i)
   ...:
   ...:
Out[4]:
{'count': 26,
 'keyword': 'Python',
 'target_period': 'm',
 'url': 'http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=m&as_drrb=q&q=Python'}
Out[4]:
{'count': 75,
 'keyword': 'Ruby',
 'target_period': 'm',
 'url': 'http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=m&as_drrb=q&q=Ruby'}
Out[4]:
{'count': 31,
 'keyword': 'Perl',
 'target_period': 'm',
 'url': 'http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=m&as_drrb=q&q=Perl'}
Out[4]:
{'count': 172,
 'keyword': 'Java',
 'target_period': 'm',
 'url': 'http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=m&as_drrb=q&q=Java'}

ソースコードは以下の通りです。REP 8を少し意識しながら書いてみましたが、徹底できているか自信なし。ソースコードチェッカやフォーマッタを使った方が良いかも。

  • countgooglenews.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import urllib2, time
from BeautifulSoup import BeautifulSoup

def count_google_news(word, target_period='m'):
    """
word          : UTF8 text
target_period : 'h' hour
                'd' day
                'w' week
                'm' month (default)
"""

    base_url = 'http://news.google.co.jp/news?ie=UTF-8&ned=jp&hl=jp&as_qdr=%s&as_drrb=q&q=%s'

    quoted_word = urllib2.quote(word)
    if target_period in 'hdwm':
        url = base_url % (target_period, quoted_word)
    else:
        raise Exception("Inappropriate 'target_period' is specified.")

    opener = urllib2.build_opener()
    opener.addheaders = [('User-Agent',
                          'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)')]

    time.sleep(1) # avoid excessive query

    html = opener.open(url).read()
    soup = BeautifulSoup(html)

    try:
        count_str = soup.find('td',
                              bgcolor="#efefef",
                              nowrap="nowrap",
                              align="right",
                              width="40%").findAll('b')[3].string
        return {'keyword': word, 'count': int(count_str),
                'url': url, 'target_period': target_period}
    except IndexError:
        return {'keyword': word, 'count': 0,
                'url': url, 'target_period': target_period}

def print_result(result):
    """
result: result must be result of count_google_news()
"""
    print "-" * 80
    print "Keyword        : " + result.get('keyword')
    print "Number of hits : " + str(result.get('count'))
    print "URL            : " + result.get('url')
    print "Target period  : " + result.get('target_period')

def main():
    sample_keyword = 'google'
    for i in 'hdwm': # check 4 times changing target period
        result = count_google_news(sample_keyword, i)
        print_result(result)

if __name__ == '__main__':
    main()

ポイントは以下の通り。

  • 読み込むモジュールを減らしてみた
  • 元ネタの"take out appropriate tag"の部分を簡略化してみた
  • 検索対象の期間を指定できるようにしてみた (無意味っぽい)
  • 少し使いまわしできるようにしてみた (クラス化した方がベターっぽいけど、selfが面倒だったりするので)

検索結果の数だけじゃなくて、検索結果のアレコレを取得できるようにしてクラスにすると使い勝手が良いかも。どこかの誰かの参考になれば幸いです。