trash-area.com ≫ blog ≫ GAE ≫ GmailフィードとGmailスクレイピング
POP3 も IMAPも使えない環境でGMailの本文を受信しようといろいろ試行錯誤した残念な結果です。
やりたかったことは限られた環境内での GMailのメール駆動アプリの開発です。
もちろん メールの .filter もムリな環境です。
そもそもスクレイピングするっていう時点でほぼサーバサイドなわけですが
それでいて POP3 も IMAPも使えないなんて状況あるんでしょうかね。
まー、結論からすると Google App Engine がそうです。はい。
Google App Engine で GMail を受信したらスクリプトを起動させたかったのですが
現時点のわたくしの脳みそではできませんでした。
ちなみに smtp2web という webサービスがありますが
これなら外部のサーバでそのままアプリ作ったほうがいいかなーと。
ということで Google App Engine でメール受信はできなかったのに加えて、
POP3 も IMAP も(.filter も)使えない環境ってのがほかに思い浮かばなかったので
今のとこ、どこにも活用できそうも無いためここに貼り付けます。
Google App Engine でメール受信アプリをしようとしてたため、
サンプルは Google App Engine(Python)のソースになってますが、開発サーバでしか動作しません。
いろんなところで言及されてますが、
https://mail.google.com/mail/feed/atom/label/
で、特定のラベルの未読メールを atom で取得できます。(これ以外にもいっぱいあります)
なので、こいつを cron で叩いて擬似的なメール駆動のトリガーに。
username = 'hoge' # hoge@gmail.comなら password = 'xxxxxx' label = 'Ameba' base64string = base64.encodestring('%s:%s' % (username, password))[:-1] headers = {'Authorization': "Basic %s" % base64string} url = 'https://mail.google.com/mail/feed/atom/%s' % label result = urlfetch.fetch(url, '', urlfetch.GET, headers) dom = fromstring(result.content) namespace ='http://purl.org/atom/ns#' items = dom.findall('.//{%s}entry' % namespace) for item in items: l = item.find('./{%s}link' % namespace) m = re.search('message_id=(.*?)&', l.get('href')) thid = m.group(1) # スレッドID(?) |
Basic 認証で叩きます。
link要素の href属性に本文へのアドレスが入ってるのでそこからスレッドID(?)を抜き出してます。
ここでは省略してますが、タイトルやらいろいろ取れます。
上で取得したスレッドIDから Gmailをスクレイピングするんですけど
まともにやると結構難儀そうなのと、「メールのソースを取得したかった」ので
ここのリンクを生成することにします。
パラメータ「ik=14f89f4596」の意味がわからなかったんですけど、たぶん「メールのソース」なんだと思います。環境によって違うのならご一方下さい。
url_0 = 'https://mail.google.com/mail/' url_1 = 'https://www.google.com/accounts/ServiceLoginBoxAuth' url_2 = 'https://www.google.com/accounts/CheckCookie?chtml=LoginDoneHtml' url_3 = 'https://mail.google.com/mail/h/' url_4 = 'https://mail.google.com/mail/?ui=&ik=14f89f4596&view=om&th=%s' login_params = {'continue': url_0, 'Email': 'hoge@gmail.com', 'Passwd': 'xxxxxx', } params = urllib.urlencode(login_params) headers = {} result = urlfetch.fetch(url_1, params, urlfetch.POST, headers, True) ck = Cookie.SimpleCookie() ck.load(result.headers['set-cookie']) s = '' s += ck['GAUSR'].output(attrs=[], header='') + ',' s += ck['LSID'].output(attrs=[], header='') + ',' s += ck['SID'].output(attrs=[], header='') + ',' headers = {'Cookie': s} result = urlfetch.fetch(url=url_2, method=urlfetch.POST, headers=headers) result = urlfetch.fetch(url=url_3, method=urlfetch.GET, headers=headers, follow_redirects=True) ck.load(result.headers['set-cookie']) s = '' s += ck['GMAIL_AT'].output(attrs=[], header='') + ',' s += ck['GX'].output(attrs=[], header='') + ',' s += ck['S'].output(attrs=[], header='') + ',' headers = {'Cookie': s} result = urlfetch.fetch(url=url_4 % thid, method=urlfetch.GET, headers=headers, follow_redirects=True) print result.content |
1. https://www.google.com/accounts/ServiceLoginBoxAuth を POST で叩きます。
2. Cookie が返ってくるので必要なやつをくっつけて https://www.google.com/accounts/CheckCookie?chtml=LoginDoneHtml に POST。
3. https://mail.google.com/mail/h/ に GET。これは携帯用のGMailアドレスです。1. で指定した continue パラメータの値(PC用)と違いますが、GAEでPC用だとリダイレクトの数が多すぎてエラーになったからです。GAE でなければ素直に PC用のを指定しても問題ないかと思います。
4. 今度はGmail用のCookieが返ってくるので、それをくっつけて https://mail.google.com/mail/?ui=&ik=14f89f4596&view=om&th={スレッドID} を呼ぶとメールのソースが取得できます。
本番サーバで動かなかったのでメール本文のデコード処理等はくっつけてません。
リクエストヘッダをいろいろいじったのですけど、開発サーバと本番サーバの違いは keep-alive くらいしかありませんでした。
GAE でうまく動いた方がいらっしゃれば教えてください。
ちなみに CookieJar が使える環境ならもうちょっとシンプルです。
もちろんGAEでは使えません。
cj = CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) opener.addheaders = headers result = opener.open(url_1, params) result = opener.open(url_2) result = opener.open(url_0) result = opener.open(url_4 % thid) print( result.read() ) |
[…] 参考: GmailフィードとGmailスクレイピング | trash-area.com […]