feedparser タグの一覧です(3 件)

[Python]feedparserのバージョンを上げたらハマったという話

先日、さくらVPSのプランをメモリ2Gのプランに変更したので、引越し作業をしたのですが、使用しているfeedparserのバージョンを最新にしたらエラーが出てしまいました。
まずはバージョンが5.0.1の場合、

/Users/aoshiman% workon old_feedparser
(old_feedparser)/Users/aoshiman% pip freeze           
feedparser==5.0.1
(old_feedparser)/Users/aoshiman% python
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import feedparser
>>> feed = feedparser.parse('http://keiba.radionikkei.jp/keiba/rss2/news/')
>>> for i in feed.entries:
...     print i.date
... 
Sat, 16 Jun 2012 08:11:18 +0000
Sat, 16 Jun 2012 08:09:06 +0000
Sat, 16 Jun 2012 08:00:14 +0000
Sat, 16 Jun 2012 07:50:20 +0000
Sat, 16 Jun 2012 07:49:55 +0000
Sat, 16 Jun 2012 07:49:17 +0000
Sat, 16 Jun 2012 07:27:45 +0000
Sat, 16 Jun 2012 07:20:56 +0000
Sat, 16 Jun 2012 07:12:11 +0000
Sat, 16 Jun 2012 07:06:18 +0000
>>> 
このように日付が取得出来ますが、これが5.1.2の場合、

(old_feedparser)/Users/aoshiman% deactivate 
/Users/aoshiman% workon new_feedparser 
(new_feedparser)/Users/aoshiman% pip freeze           
feedparser==5.1.2
(new_feedparser)/Users/aoshiman% python
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import feedparser
>>> feed = feedparser.parse('http://keiba.radionikkei.jp/keiba/rss2/news/')
>>> for i in feed.entries:
...     print i.date
... 
Traceback (most recent call last):
  File "", line 2, in 
  File "/users/aoshiman/.virtualenvs/new_feedparser/lib/python2.6/site-packages/feedparser.py", line 424, in __getattr__
    raise AttributeError, "object has no attribute '%s'" % key
AttributeError: object has no attribute 'date'
>>> 

このようにdateなんて知らないよーって出ます。

色々調べたところ、この現象はfeedparserのIssueに掲載されていました
Issue 340 - feedparser - "date" attribute not in 5.1.1 - Parse Atom and RSS feeds in Python - Google Project Hosting
要は、もうentries.dateでは要素にはアクセス出来ませんよ、entries.publishedを使って下さいとのことのようです。

>>> import feedparser
>>> feed = feedparser.parse('http://keiba.radionikkei.jp/keiba/rss2/news/')
>>> for i in feed.entries:
...     print i.published
... 
Sat, 16 Jun 2012 08:11:18 +0000
Sat, 16 Jun 2012 08:09:06 +0000
Sat, 16 Jun 2012 08:00:14 +0000
Sat, 16 Jun 2012 07:50:20 +0000
Sat, 16 Jun 2012 07:49:55 +0000
Sat, 16 Jun 2012 07:49:17 +0000
Sat, 16 Jun 2012 07:27:45 +0000
Sat, 16 Jun 2012 07:20:56 +0000
Sat, 16 Jun 2012 07:12:11 +0000
Sat, 16 Jun 2012 07:06:18 +0000
>>> 

Pythonで1日のGoogle検索履歴の一覧を作成してGmailから送信する

今の私にとって(他の人もそうだと思いますが)、仕事プライベートに関係なく、Google検索は無くてはならないものですが、はたして1日にどのくらい検索しているのか知りたくて、リストを作成してみました。併せて前回のYahoo!天気情報のRSSと同様にGmailで送信しています。役に立つか分かりませんが、作成したコードを掲載します(スクリプトは何度も実行して成功しているものですが、実施は自己責任でお願いします)。尚、Google検索の履歴(Google Search History)はGoogleアカウントでログインしている状態で有効になります。
作成した時のポイントとしては

  • Google Search History は RSS で取得出来るので、feedparserを利用した
  • RSS は Basic認証がかかる為、urllibのFancyURLopenerを使用した
  • RSSのURLは件数のパラメータ(&num=)が無い場合、25件しか取得出来ないようなので(自分調べ)、1日で必要な件数を設定した
  • 取得出来る日時がGMTなので、日本時間(+9h)にする方法に悩んだ
# coding:utf-8

import urllib
import feedparser
import email.Utils
from time import *

import smtplib
from email.MIMEText import MIMEText
from email.Header import Header
from email.Utils import formatdate


class MyURLopener(urllib.FancyURLopener):
    def prompt_user_passwd(self, host, realm):
        return ('YOUR_GMAIL_ADDRESS', 'YOUR_PASSWORD')


def feed_parse(u):
    f = opener.open(u)
    d = feedparser.parse(f)
    TEMPLATE = '* %(entry_date)s : %(entry_title)s'
    feed = []
    for entry in d.entries:
        feed.append([entry.date, entry.title])
    feed.reverse()

    item_list = []
    today = localtime(time())[0:3]
    for i in feed:
        entry_date, entry_title = i[0], i[1]
        entry_date = localtime(mktime(email.Utils.parsedate(entry_date)) + 32400)
        if entry_date[0:3] == today:
            entry_date = strftime('%Y/%m/%d %H:%M:%S',entry_date)
            item_list.append(TEMPLATE % locals())
    items = '\n'.join(item_list)

    return items

def create_message(from_addr, to_addr, subject, body, encoding):
    msg = MIMEText(body.encode(encoding), 'plain', encoding)
    msg['Subject'] = Header(subject, encoding)
    msg['From'] = from_addr
    msg['To'] = to_addr
    msg['Date'] = formatdate()

    return msg

def send_via_gmail(from_addr, to_addr, msg):
    s = smtplib.SMTP('smtp.gmail.com', 587)
    s.ehlo()
    s.starttls()
    s.ehlo()
    s.login('YOUR_GMAIL_ADDRESS', 'YOUR_PASSWORD')
    s.sendmail(from_addr, to_addr, msg.as_string())
    s.close()

if __name__ == '__main__':
    number = '200'
    URL = 'http://www.google.com/searchhistory/?output=rss&num=%s' % number
    opener = MyURLopener({})
    subject = 'Google search history'
    body = feed_parse(URL)
    from_addr = 'YOUR_GMAIL_ADDRESS'
    to_addr = 'xxxxxxxxxxxxx@gmail.com'
    msg = create_message(from_addr, to_addr, subject, body, 'UTF-8')
    send_via_gmail(from_addr, to_addr, msg)

実際に送ってみるとこんなかんじです。これは一部分で、調べものが多いときは100件以上/日は検索していました。
Gmail

少しとはいえ、自分の検索を晒すのは恥ずかしい><。Typoとか(笑。
これを応用すれば、twitterで検索履歴をポストすることも出来そう。とっても恥ずかしいけどね。

参考サイト


PythonでYahoo!天気情報のRSSをパースしてGmailから送信する

最近、Web上の色々なコードを写経したり、変更を加えたりして少しずつPythonの勉強をしていますが、今回Setomitsさんのblogで拝見した天気予報の定期送信スクリプトを自分なりにアレンジし、Gmailから送信出来るように変更してみました。パースした内容の加工は何もしていません(したいけどまだ勉強中)。使用方法は、第1引数に送信先のメールアドレス、第2引数に地域コード(静岡県中部は5010)を与えます。書いたコードは下記の様になりました。

# coding: utf-8

to_addr = sys.argv[1]
area = sys.argv[2]

def create_contents(u):
    data = feedparser.parse(u)
    f = [data.feed.title] + [entry.title for entry in data.entries]
    s, b = f[0], f[1:]

    return '\n'.join(b), s

def create_message(from_addr, to_addr, subject, body, encoding):
    msg = MIMEText(body.encode(encoding), 'plain', encoding)
    msg['Subject'] = Header(subject, encoding)
    msg['From'] = from_addr
    msg['To'] = to_addr
    msg['Date'] = formatdate()
    return msg

def send_via_gmail(from_addr, to_addr, msg):
    s = smtplib.SMTP('smtp.gmail.com', 587)
    s.ehlo()
    s.starttls()
    s.ehlo()
    s.login('YOUR_GMAIL_ADDRESS', 'YOUR_PASSWORD')
    s.sendmail(from_addr, to_addr, msg.as_string())
    s.close()

def main():
    from_addr = 'YOUR_GMAIL_ADDRESS'
    url = 'http://rss.weather.yahoo.co.jp/rss/days/%s.xml' % area
    body, subject = create_contents(url)
    msg = create_message(from_addr, to_addr, subject, body, 'UTF-8')
    send_via_gmail(from_addr, to_addr, msg)

if __name__ == '__main__':
    main()

ここで問題(というか不思議な現象)が発生。携帯(SoftBank)やISPのアドレスに送ったメール内容はこのような感じになりますが

webmail
Gmailへ送った場合は途中で内容が切れてしまいます。またFromアドレスであるGmailの送信済みメール内容は、どの送信アドレスに送ったにも関わらず同じように途中で内容が切れてしまっています。

gmail

とりあえずメールは携帯へ送ることになるので困りませんが、この現象については継続して調べていきます。
[2008年9月30日追記]
時間が掛かりましたが、コメントあったようにエンコード関係だったようで、コードの修正をしました。
[追記ここまで]

参考サイト


PAGE TOP