PythonでXMLの要素を抜き出す

XMLを解析し必要なデータ(URL、タイトル等)を集める
・検索をかけるページのデータを受信する(http)
・検索範囲を特定し検索を行う(文字コードに注意する)

おおまかに分けてこの3つをクリアする必要がある。
まずは、XMLの解析なのですが、ここでは単純なXMLを使ってタイトルとリンクを抜き出すまでをやってみます。
コードはダサダサなので、何かもっと良い方法があれば教えてください。(-人-)

[ Sample.xml ]



 
  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%AB%C6%FC%BF%B7%CA%B9">朝日新聞</a>の社会面
  http://www.asahi.com/national/list.html
 


  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%AB%C6%FC%BF%B7%CA%B9">朝日新聞</a>のスポーツ面
  http://www.asahi.com/sports/list.html
 

 
  <a class="keyword" href="http://d.hatena.ne.jp/keyword/%C4%AB%C6%FC%BF%B7%CA%B9">朝日新聞</a>の政治面
  http://www.asahi.com/politics/list.html
 

[ Sample.py ]

def testNode(node):
  titleNodes = node.getElementsByTagName('title')
  linkNodes = node.getElementsByTagName('link')
  if linkNodes.length == titleNodes.length:
   i=0
   while i < linkNodes.length:
    print titleNodes[i].firstChild.data + " : " + linkNodes[i].firstChild.data
    i+=1
  else:
   print "Error!"

if __name__ == '__main__':
 doc = minidom.parse('Sample.xml')
  testNode( doc )

[ 実行結果 ]

朝日新聞の社会面 : http://www.asahi.com/national/list.html
朝日新聞のスポーツ面 : http://www.asahi.com/sports/list.html
朝日新聞の政治面 : http://www.asahi.com/politics/list.html

とりあえず、データの抽出完了です^^。

PythonでXMLを操作する

今の仕事で、RSS形式のURL一覧から指定文字列が見つかるリンクのみを抽出する処理を全てC++で1件ずつダウンロードして、本文から検索してっていうアプローチでとてもパフォーマンスが悪い。
だから、ダウンロードせずにサーバー側で抽出を行って、その結果だけを返すようにしようと考えている。

しかも高速にしなければならない。

そこで、PythonからXMLを扱うために色々調べてたら、二十代は模索のときブログさんの所に有益な情報があったので、メモさせて貰います。

PythonでXMLを扱う(1)
PythonでXMLを扱う(2)
PythonでXMLを扱う(3)
PythonでXMLを扱う(4)
PythonでXMLを扱う(5)
PythonでXMLを扱う(6)
PythonでXMLを扱う(7)
PythonでXMLを扱う(8)

COM難しいよー(T T) (2)&(3)

昨日の「COM難しいよー」問題。

うまくいかない原因は判明しました。
そう、うまくいかない原因

成功したテスト用と今作ってるやつと何が違うのか、色々比べてみたら「プロジェクトの種類」が違っていることに今さらながら気づいたわけです。

で、

成功してたのが Win32コンソールプロジェクト
失敗してたのが、MFCプロジェクト

どうやらMFCにはMFCのCOMの実装手順があるみたいです。
細かく言うと、接続ポイントとか、DISPインターフェースをマップしたり他にも何かしなくちゃいけないかもだけど、今日はここで力尽きた...

MFC特有の実装というものはありませんでした。もう一度、シンプルなテスト用のイベントシンクをMFC上で走らせてみたら普通に動いた。

こうなったら確実にできそう&検索でもひっかかりそうな ATLを使ってみようかなと思ったりしてますが、どうなんでしょうね。
危うく、未開拓地であるATLに手を出す所でした...危ない危ない。COMも十分オーバーテクノロジーだったんですが、今回の件で接続ポイント回りには詳しくなれたぞと。

解決はまだしてない。けど

どれが原因か特定できなかったから色々な方向から調べてCOMについてちょっと詳しくなった。仕事は進んで無いけど、経験値は確実に溜まっていってるはず!!

そう考えないとやってけないよ。…だってこの1週間、この問題に掛かりっきりだったし。(T^T)

とにかく、解決するまで色んなアプローチを続けてみます!

というわけで解決しました。

これが原因だった!と1つに絞りきれなかったので、
思い当たる原因を列挙。

  • importしたタイプライブラリと実行時に読み込むDLLの整合が取れていなかった?
  • ソースオブジェクト側のevent変数名と、ソースインターフェイスのメソッド名が違っていた?
  • CoCreateInstanceでコンポーネントを作成してから、FindConnectionPointまでの呼び出し方がまずかった?

最後におさらい

今回のC#でイベントソースオブジェクト、C++でイベントシンクオブジェクトを作る手順を忘れないようにメモ。

C#側(イベントソース)

[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)] ←属性に追加

[ComSourceInterfaces(typeof(/*イベントソースインターフェイス名*/))]←属性に追加

中間作業(タイプライブラリの作成)
  • RegAsm.exeを使ってC#で作ったDLLからTLBファイルを出力する
C++側(イベントシンク)
  • タイプライブラリをimport

#import "****.tlb" raw_interfaces_only named_guids

あとはCOMの流儀に従って、、、

  • コンポーネントをCoCreateInstance()
  • IConnectionPointContainerをQueryInterface()
  • IConnectionPointをFindConnectionPoint()
  • 取得したIConnectionPointをAdvise

そして、イベントシンクが必要なくなったら

  • 取得したIConnectionPointをUnadvise

参考文献

  • COMのイロハを教えてくれた本「Inside COM」(が、絶版らしいです。奇跡的に会社にあってラッキー!)
  • 接続ポイントが詳しく書かれていた本「Inside DCOM」(分かり易かった)

COM難しいよー(T T)

C#で作ったCOMコンポーネントC++から呼び出す。なんていう時代の流れにアンマッチな事してるんだけど、うまく行かなくてもうかれこれ4日目 orz

C#で作った処理をCOMに公開して、それをC++で呼んで実行まではできたんだけど、COM側での処理の進捗とかを知るためにC++側の関数をコールバックしてもらうための仕組み「イベントシンク」でつまづいてる。

C#側で実装したコンポーネント(こいつがソースオブジェクトを持ってる)のIConnectionPointContainerインターフェースまでは取れるのに、IConnectionPoint(接続ポイント)が取れない!

リターンコードは0x80040200(E_EVENT_FIRST)で、色々調べてみると、ライブラリがレジストリに登録されていないんじゃないかって結論になった。

でも、成功したテスト用とやってる事は同じなのになぜ??

Dr. GUI と COM イベント:第 1 部から引用させてもらいました。

Windows Vista Service Pack 1 を手動でインストールしてみた。

というのも、本来ならWindows Updateで通知が来て更新する予定だったけどいつまで経っても通知が来なかったので手動で。

結果は何事もなく成功しました。

以下に手順を簡単にまとめてみました。
1.MS TechNet:Windows Vista Service Pack1にあるWindows Vista Service Pack 1 x86 (全言語用スタンドアロン版) CD ISOをダウンロードしてくる。
2.DaemonToolsなどの仮想ドライブソフトを使ってISOをマウント
3.セットアップEXEがあるのでそれを起動
4.何度か再起動する&気長に待つ。

パソコンのスペックで個人差があるけど、自分のパソコンでは1時間30分ほどで全て完了しました。

無事にSP1を適用できました。