Beautiful Soup 4.4.0 で extract() を使うとDOM treeが壊れる?
Python で Beautiful Soup 4.4.0 を使った時に遭遇した問題。stackoverflow でも取り上げられていて、取り敢えずは 4.3.2 に戻すことで対処しました。
環境
問題点
次のようなコードで、html中からscriptタグを除去していたところ 4.0 の環境でおかしな動作が起きた。
soup = BeautifulSoup(page_html, 'lxml') [s.extract() for s in soup('script')]
この処理の後、soup('body') の結果が None になってしまうという現象が発生。また、[s.extract() for s in soup('script')] を何度実行しても消せないscriptタグが出たりと。いずれも4.3.2では、起きてなかった問題でした。
対策
前述の stackoverflowのエントリー を見つけて読んだ所、 extract() 後に 二重改行がはいることでおかしくなるとの回答がある。
解決方法として 1. str(soup) を再度BeautifulSoupでパースする 2. html5lib パーサーを使う が提案されていた。また別の回答としては 4.3.2 だと大丈夫ともある。
僕の環境の場合、4.4.0必須ではなかったのと pip で管理していたのでバージョン固定が簡単にできるということで、4.3.2 固定にして使うことにした。
# pip install beautifulsoup4==4.3.2
urllib2.urlopen() で GET/POST を使い分け
Python の urllib2 で、ちょっとした仕様に気づいてなかったのでメモ。
urlopen() の 第2引数 data を渡すと、必ずPOSTの挙動になるようです。
確認環境:
POST Data
なにげに data を渡すと、POST methodが送られる Requestオブジェクトが作られます。HOWTOからコードを抜粋。
import urllib import urllib2 url = 'http://www.someserver.com/cgi-bin/register.cgi' values = {'name' : 'Michael Foord', 'location' : 'Northampton', 'language' : 'Python' } data = urllib.urlencode(values) req = urllib2.Request(url, data) response = urllib2.urlopen(req)
このように確認できます。
In [9]: req.get_method() Out[9]: 'POST'
参考:
GET with Data
でも、多くのサイトで GET パラメーターでデーターを送りたいこともあります(よね?)。dataを渡さなければいいんですが、個人的には、この書き方が綺麗だなぁと思いました。
...前半は POST Data と同じ...
data = urllib.urlencode(values)
req = urllib2.Request(url + ('?%s' % data))
response = urllib2.urlopen(req)
確認すると、ちゃんとGETになっています。
In [9]: req.get_full_url() Out[9]: 'http://www.someserver.com/cgi-bin/register.cgi?name=Michael+Foord&language=Python&location=Northampton' In [10]: req.get_method() Out[10]: 'GET'
python, Django でドキュメント関連ツール
他の人が書いたコードを読む時に、全体像の把握がしたくなります。そこで、ソースからドキュメントが作れるツールをいくつか探してみました。
環境:
試用ツール:
クラス図とコールグラスなどを生成:Doxygen
クラスの継承関係とかが把握できるドキュメントを生成してくれます。
Ubuntuの場合、次のコマンドだけでインストール完了。Graphvizは、Doxygen内で生成されるDOTファイルにもとづいて画像を生成するときに使われるコンポーネントのようです。
$ sudo apt-get install doxygen graphviz
次のような流れでドキュメントを生成できます。
$ doxygen -g # 設定ファイルの生成 ... 設定ファイル:Doxygen を編集... $ doxygen # 設定ファイルに基づき、ドキュメント生成
- できた html は、こんな雰囲気。
Django テンプレートで楽する技(初心者向け)
高機能はDjango、なかなか全貌が把握できてませんが、こりゃ楽だぁ〜と思った機能を3つ紹介。
数値に桁区切りのカンマを入れる方法
humanize というアプリが同梱されているので、これを使うことでテンプレートだけで対応が可能でした。
humanize は templatetags がいくつか入ってるアプリです。カンマ区切りの intcomma 以外は、日本語アプリではあまり使わなさそうだな。
使い方は3ステップ+αで完了。
- settings.py の INSTALLED_APPS に django.contrib.humanize を追加
- テンプレートにロードの記述 {% load humanize %} を追加
- 該当箇所に intcomma フィルタを適用
ただしロケールにjaを使っている場合には、もう一つおまじないが必要でした
- settings.py で NUMBER_GROUPING = 3 を追加 ※ja locale ではデフォルトで設定されてない為
テンプレート系の処理の為か、エラーも表示されないので注意が必要ですね。