urllib
urllibを使ってみます。
- urllib.urlopenの引数にURLを入れる
- 返ってきたオブジェクトはファイルのように扱える
基本的にはこれだけです。簡単ですね。
# get.py import sys import urllib print urllib.urlopen(sys.argv[1]).read()
実行例は以下のようになります。
> python get.py http://d.hatena.ne.jp/pythonco/ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=euc-jp"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>pythonco(ぱいそんこ)の日記</title> <link rel="start" href="./" title="pythonco(ぱいそんこ)の日記"> <link rel="help" href="/help" title="ヘルプ"> <link rel="prev" href="/pythonco/?of=5" title="前の5日分"> ...
> python get.py http://www.hatena.ne.jp <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <link rel="start" href="http://www.hatena.ne.jp/" title="・ ・> <link rel="stylesheet" href="/css/base.css" type="text/css" media="all"> <link rel="search" type="application/opensearchdescription+xml" href="http://search.hatena.ne.jp/opensearch/all.xml" tit <link rel="search" type="application/opensearchdescription+xml" href="http://q.hatena.ne.jp/opensearch/question.xml" tit <title>・・・/title> <meta name="description" content="??・鋍腓障・・・吟㏍若・若х蕭罘純㏍違篋冴℡査膈篋阪罎膣・Q&A鐚純若激c・・若・RSS・若 <meta name="keywords" content="・・・hatena,篋阪罎膣↑純若激c・・若・㏍穐ゃ≪・蒔RSS,≪・祉壕В% ...
文字化けしてしまいました。仕方がないのでヘッダのcharsetを見てencodeしてみます。
# get.py import sys import urllib f = urllib.urlopen(sys.argv[1]) c = f.headers.getparam('charset') print c print unicode(f.read(), c).encode('euc-jp')
> python get.py http://www.hatena.ne.jp/ utf-8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <link rel="start" href="http://www.hatena.ne.jp/" title="はてな"> <link rel="stylesheet" href="/css/base.css" type="text/css" media="all"> <link rel="search" type="application/opensearchdescription+xml" href="http://search.hatena.ne.jp/opensearch/all.xml" tit <link rel="search" type="application/opensearchdescription+xml" href="http://q.hatena.ne.jp/opensearch/question.xml" tit <title>はてな</title> <meta name="description" content="株式会社はてなが運営。キーワードで繋がる高機能ブログ、人がたずね人が答える人力検索(Q& く便利になるサービスが揃っています。"> <meta name="keywords" content="はてな,hatena,人力検索,ソーシャルブックマーク,ブログ,ダイアリー,RSS,アクセス解析"> <link rel="stylesheet" href="/css/top.css" type="text/css" media="all"> <link rel="stylesheet" href="/css/minwidth.css" type="text/css" media="all"> <SCRIPT type="text/javascript"> <!-- var cookie_name = "PORTAL_TAB"; ...
これで完璧かな、などと思っていたのですが、charsetを返さないサーバもあるので困りました。
> python get.py http://www.google.co.jp None Traceback (most recent call last): File "get.py", line 17, in ? print unicode(f.read(), c).encode('euc-jp') TypeError: unicode() argument 2 must be string, not None
仕方がないので片っ端からunicodeに変換して、例外が出なかった文字コードを採用する、という方法でやってみます。
# get.py import sys import urllib import encodings def encode(s, c): for i in encodings.aliases.aliases: try: return unicode(s, i).encode(c), i except: pass return s, None s, e = encode(urllib.urlopen(sys.argv[1]).read(), 'euc-jp') print e print s
> python get.py http://www.google.co.jp mskanji <html><head><meta http-equiv="content-type" content="text/html; charset=Shift_JIS"><title>Google</title><style><!-- body,td,a,p,.h{font-family:arial,sans-serif} .h{font-size:20px} .h{color:#3366cc} .q{color:#00c} --></style> <script> <!-- function sf(){document.f.q.focus();} // --> </script> </head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload=sf() topmargin=3 marginheight= idth=100%><font size=-1><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.co.jp/ig%3Fhl%3Dja&usg=__zzRfDx_8QtfWxWHbI https://www.google.com/accounts/Login?continue=http://www.google.co.jp/&hl=ja">ログイン</a></font></div><img alt="Google br><form action="/search" name=f><table border=0 cellspacing=0 cellpadding=4><tr><td nowrap><font size=-1><b>ウェブ</b>& o.jp/imghp?ie=Shift_JIS&oe=Shift_JIS&hl=ja&tab=wi">イメージ</a> <a class=q href="http://news.goog ...
まあとりあえずこれでいい、のかな……。
簡単なProxyを作ってみた
参考資料
参考資料ではSimpleHTTPServer.SimpleHTTPRequestHandlerのdo_GETをオーバーライドしていますが、必要なものはdo_GETとcopyfileだけなのでBaseHTTPServer.BaseHTTPRequestHandlerでいいや、と思ったのでした。
# -*- coding: euc-jp -*- import BaseHTTPServer import os import shutil import StringIO import urllib class ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler): def encode(self, s, c): for i in ('euc-jp', 'sjis', 'utf-8'): try: return unicode(s, i).encode(c), i except: pass return s, None def do_GET(self): print 'get...', self.path f = urllib.urlopen(self.path) if 'text' in f.info().gettype() and os.path.splitext(self.path)[1] in ('', '.htm', '.html', '.cgi', '.php'): s, e = self.encode(f.read(), 'euc-jp') if e: s = s.replace('。', '(笑') f = StringIO.StringIO(self.encode(s, e)[0]) shutil.copyfileobj(f, self.wfile) port = 3128 print 'proxy at', port BaseHTTPServer.HTTPServer(('', port), ProxyHandler).serve_forever()
使い方
- python proxy.py で起動
- ブラウザの設定をいじって起動したproxyに繋ぐ
- 日本語のページを見たときに '。' が '(笑' に書き換わってイラッとする
ときどき書き換わらなかったりするのは仕様です。嘘です。よくわかりません。
処理の流れ
- ブラウザが何かをGETしようとするとdo_GETが呼ばれて、self.pathにブラウザがGETしようとしているURLが入る
- urllib.urlopenでself.pathをGET
- GETした結果得られるものはファイルオブジェクトっぽいものなのでreadで文字列だけを取り出して書き換える
- StringIOで文字列からファイルオブジェクトっぽいものに変換
- 変換したファイルオブジェクトっぽいものをshutil.copyfileobjでself.wfileにコピー
- 最終的にブラウザに表示されるものはself.wfileの中身