いかにして効率よく大量のおっぱい画像をダウンロードするか というエントリを読んだら、私の中に潜むおっぱいマニア(Python 使いのこと)の血が騒いで、勢いで書いてしまった。後悔はしていない。

で、これを作って動かしてみて気づいたんだけど、Yahoo! の画像検索の API では、最大で 1000 枚までしか検索できない。なのに元記事では 7000 枚以上もダウンロードできてる…時間を置いて検索しなおすと検索結果が変わって、新しい画像がゲットできるとか?おっぱいマニアへの道は遠くて険しい
それから、 SimpleXML というクラスは演算子のオーバロードを学ぶために私が大昔に作ったもので、いわば習作。当時は今もだけど XML についてよく理解していなかった。だからこれは参考にしないで、 Python2.4.2でPHP5のSimpleXMLを真似 で公開されているものとか、あるいは Beautiful Soap (というもの。まだ私は試してないけど)を使った方がいいかも。それ以外でも XML をパースして、ハッシュと属性参照でアクセスできるようなツリーを作るライブラリの何かいいやつがあったら教えてください。やっぱり私はまだ、おっぱいマニアにはほど遠い。

ちなみにダウンロードした 1000 枚のおっぱい画像のファイルサイズは、合計で 108 Mほどでした。

#! /usr/bin/python
# -*- coding:utf8 -*-

from urllib import quote, urlopen
import time
import xml.dom.minidom as minidom

class SimpleXML(object):
    def __init__(self, minidom_obj):
        self.dom = minidom_obj

    def __getitem__(self, key):
        if self.dom.attributes.has_key(key):
            return self.dom.getAttribute(key)
        raise KeyError

    def __getattr__(self, attrname):
        if attrname in dir(self.dom):
            tmp = eval("self.dom."+attrname)
            if isinstance(tmp, xml.dom.minidom.NodeList):
                return map( lambda x: SimpleXML(x), tmp)
            elif isinstance(tmp, xml.dom.minidom.Node):
                return SimpleXML(tmp)
            else:
                return tmp
            return self.buff[attrname]
        return map( lambda x: SimpleXML(x),
                    filter(lambda x: x.tagName == attrname,
                           filter( lambda x: not (isinstance(x, xml.dom.minidom.Comment) or
                                                  isinstance(x, xml.dom.minidom.Text)),
                                   self.dom.childNodes)))

    def __unicode__(self):
        if len(self.dom.childNodes) == 1 and isinstance(self.dom.childNodes[0], xml.dom.minidom.Text):
            return self.dom.childNodes[0].data

imageNum = 0
totalResultsAvailable = 2

data = {}
data["appid"] = "****"
data["query"] = "おっぱい"
data["type"]  = "all"
data["results"] = 50
data["format"] = "any"
data["adult_ok"] = 1 # ここ重要!!!
data["start"] = 1

while data["start"] < totalResultsAvailable:
    res = urlopen( "http://api.search.yahoo.co.jp/ImageSearchService/V1/imageSearch?"
                   + "&".join(["=".join([key, quote(str(value))]) for key, value in data.items()]))
    res = res.read()
    print res
    document = minidom.parseString(res)
    sdoc = SimpleXML(document)
    totalResultsAvailable = int(unicode(sdoc.ResultSet[0]["totalResultsAvailable"]))
    time.sleep(1)
    for result in sdoc.ResultSet[0].Result:
        img = urlopen(unicode(result.Url[0]))
        if img.info().gettype()[:5] != "image":
            img.close()
            img = urlopen(unicode(result.Thumbnail[0].Url[0]))
        if img.info().gettype()[:5] == "image":
            print unicode(imageNum)+"."+unicode(result.FileFormat[0])
            localfile = file(unicode(imageNum)+"."+unicode(result.FileFormat[0]),"wb")
            localfile.write(img.read())
            img.close()
            localfile.close()
            imageNum += 1
    data["start"] += data["results"]
2007.10.19 Fri l Python l COM(2) TB(1) l top ▲

コメント

XML をパースするライブラリ
はじめまして.
リンクしていただきましたtomoemonです.

>XML をパースして、ハッシュと属性参照でアクセスできるような
lxmlやElementTreeといったものがよく使われているようです.ElementTreeはピュアPython,lxmlはCによる実装ですので速度的にはlxmlの方が有利でしょうか.

SimpleXMLのようなアクセス方法についてはlxmlのobjectifyを用いることで,ほぼ実現することができます.属性をハッシュで参照できないのは少々残念ですが,XPathも利用することができるのでXML操作をだいぶ楽にしてくれるライブラリだと思います.もしよければお試しください.
http://pypi.python.org/pypi/lxml/1.3.4
http://codespeak.net/lxml/index.html

>>
from lxml import objectify

data = yahooのリクエスト結果
root = objectify.fromstring(data)
# 属性の参照はget関数
print root.get("totalResultsReturned")
#子ノードはアトリビュートで参照
for e in root.Result:
 print e.Url, e.Title
<<

P.S.
私も試してみましたが,YahooのAPIで1000枚以上取得しているのは確かに不思議ですね(笑)
2007.10.19 Fri l tomoemon. URL l 編集
コメントありがとうございます
tomoemon さんのおかげで、また一歩おっぱいマニアに近づけました。ありがとうございます!
2007.10.19 Fri l kawasaq. URL l 編集

コメントの投稿












       

トラックバック

トラックバックURL
→http://kawasaq.blog56.fc2.com/tb.php/97-36293753
この記事にトラックバックする(FC2ブログユーザー)
GWはせっかく暇になったので、プログラミングのお勉強をしました。 私はプログラマーではありませんが、XHTML、CSS、Javascriptなどのフロントエンド技術の他、その領域に近いプログラミングはできるようになりたいと思っています。 スクレイピングなんかはできるようになっ
2008.05.05 Mon l あと味