BeautifulSoup -> IronPython <- C#

Pythonの非標準ライブラリにBeautifulSoupというHTML/XMLを解析してくれるものがあります(http://www.crummy.com/software/BeautifulSoup/)。俗に言うスクレイピング、に用います。
以前それをIronPythonで利用しようとした時、当時のIronPythonが仕様的に不完全だったために使うことが出来ませんでした。

しかしIronPythonも着々と進歩してます。
リリースされて間もないIronPython 2.6では無事インポートすることができました。
今日の実験は、IronPythonを仲介者として、PythonのBeautifulSoupをC#で使おうというものです。
C#XMLは簡単に扱えるのだけど、HTMLはそうはいかないのです。


IronPythonPython標準のモジュールが付いてこないので、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を列挙します。
出力:

: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
PythonでBeautifulSoupを使った時に何故か一行目のような変なの出るんですがこれは・・・。)
HTMLがコロコロ変わるようなサイトを扱う場合には、いちいちビルドし直さずともスクリプトを修正するだけで済むので、その点はなかなか良いですね。しかし、処理が遅いです・・・。バイトコンパイルされたスクリプトは同じようにして扱えるのかな。


以上です。おしまい。


まだβしか出ていませんが、.NET4.0向けのIronPythonというのがあります。これがC#4.0のdynamicと非常に相性が良く、互いのやり取りがより直感的になります。IronPythonのサイトにサンプルコードも載っているので気になる方は見てみてください。気にならない方は見ないでください。