BeautifulSoup -> IronPython <- C#
Pythonの非標準ライブラリにBeautifulSoupというHTML/XMLを解析してくれるものがあります(http://www.crummy.com/software/BeautifulSoup/)。俗に言うスクレイピング、に用います。
以前それをIronPythonで利用しようとした時、当時のIronPythonが仕様的に不完全だったために使うことが出来ませんでした。
リリースされて間もないIronPython 2.6では無事インポートすることができました。
今日の実験は、IronPythonを仲介者として、PythonのBeautifulSoupをC#で使おうというものです。
C#はXMLは簡単に扱えるのだけど、HTMLはそうはいかないのです。
IronPythonはPython標準のモジュールが付いてこないので、CPythonのモジュールファイルをコピーしてきてIronPython側のLibフォルダに突っ込んでやるか、実行時にCPython側のフォルダを参照(sys.path.append)するようにします。
scripts.py
# パスの追加で済ます場合は以下のように # import sys # sys.path.append( 'c:/FooBar/Python26/Lib' ) # sys.path.append( 'c:/FooBar/Python26/Lib/site-packages' ) from BeautifulSoup import BeautifulSoup # "html"の値はC#側から渡ってくる予定 soup = BeautifulSoup( html ) # BeautifulSoupの使い方は本家のドキュメント等を参照してね comments = [ x.contents[1] for x in soup.find( 'ul', {'class' : 'hatena-recentcomment' } ).findAll( 'li' ) ]
C#のコード(抜粋)
class Program { static void Main( string[] args ) { (new BeautifulSoupDemo()).Demo1(); } } class BeautifulSoupDemo { private string GetHTML() { var client = new WebClient(); using ( var page = client.OpenRead( "http://d.hatena.ne.jp/Nobuhisa/" ) ) using ( var reader = new StreamReader( page, Encoding.GetEncoding( "euc-jp" ) ) ) { return reader.ReadToEnd(); } } public void Demo1() { var ipy = Python.CreateRuntime(); var engine = Python.CreateEngine(); var source = engine.CreateScriptSourceFromFile( "./scripts.py", Encoding.Unicode ); var scope = ipy.CreateScope(); scope.SetVariable( "html", this.GetHTML() ); source.Execute( scope ); // 変数をセットしたスコープを渡して、ソースの実行 // スクリプトが実行され、commentsという変数に結果が格納されている(はず) var comments = scope.GetVariable<IronPython.Runtime.List>( "comments" ).ToList(); comments.ForEach( Console.WriteLine ); } }
これを実行すると、この日記のHTMLを解析して、最近コメントをくれた人たちのIDを列挙します。
出力:
(PythonでBeautifulSoupを使った時に何故か一行目のような変なの出るんですがこれは・・・。):1: DeprecationWarning: object.__new__() takes no parameters
T_GYOUTEN
Nobuhisa
T_GYOUTEN
Nobuhisa
zecl
zecl
Nobuhisa
sumim
zecl
Nobuhisa
zecl
Nobuhisa
rayfill
Nobuhisa
いげ太
nakayoshix
Nobuhisa
pokarim
Nobuhisa
mrkn
HTMLがコロコロ変わるようなサイトを扱う場合には、いちいちビルドし直さずともスクリプトを修正するだけで済むので、その点はなかなか良いですね。しかし、処理が遅いです・・・。バイトコンパイルされたスクリプトは同じようにして扱えるのかな。
以上です。おしまい。
まだβしか出ていませんが、.NET4.0向けのIronPythonというのがあります。これがC#4.0のdynamicと非常に相性が良く、互いのやり取りがより直感的になります。IronPythonのサイトにサンプルコードも載っているので気になる方は見てみてください。気にならない方は見ないでください。