普通のおっぱいには興味ありません

知らないところからリンクされてるなぁと開いてみると,この前はてなブックマークで無駄に盛り上がっていた*1おっぱい画像ネタだった.ぱっと見,Yahooの検索API使っているだけなのでスルーしてたけど,よくよく考えるとリンク先で指摘しているとおりYahooのAPIって1000件までしか(画像にしろ,Webにしろ)取得できないので8000個の画像を取ってくるのは難しいように思える.ちなみに,この制限はyahoo.comのAPIでも同じ.
Kawasaq通信 - FC2 BLOG パスワード認証
検索:画像検索API - Yahoo!デベロッパーネットワーク
Yahoo! Search BOSS - YDN


PythonXML操作に使えるライブラリlxmlの練習ついでにちょっと遊んでみた.objectifyを使う場合は特に問題なかったけど,XPathを使う場合は単純にタグ名を指定しただけでは空配列が返ってくるばかりで使うことができない.XPathを指定する際はAPIから返ってくるXMLのルート要素であるResultSetのxmlns要素を名前空間として指定しなければ取得できないらしい.lxmlのFAQにそれっぽいことが書いてあったんだけど気づくのに時間がかかった.タグ名を取得してもXMLの見た目そのままではなく「{名前空間}タグ名」という値が返ってくる.
lxml 1.3.4 : Python Package Index
404 Not Found


取ってきた画像.少し自重してみた.

結局8000件取得ってなんなんだろうな.わからなかったorz
こんなアホなことしてる場合じゃないのに・・・スルー力が足りない(笑)
ソースは以下の通り.特に面白いことはない.

# -*- coding: sjis -*-
import os, sys
import time
import urllib
from lxml import etree
from lxml import objectify

def main():
  keyword = "ひんぬー"
  max_num = 1000
  count = 0
  start = 1
  
  if not os.access(keyword, os.W_OK):
    os.mkdir(keyword)
  
  while count < max_num:
    result = search(start, keyword)
    if not result:
      break
    for url in result:
      # URLから拡張子の取得
      ext = url.split('/')[-1].split(".")[-1].upper()
      if ext != "JPG" and ext != "JPEG":
        continue
      filename = ("%05d." % count) + ext.lower()
      filepath = os.path.join(keyword, filename)
      
      retry = 0
      while retry < 3:
        time.sleep(0.1)
        try:
          urllib.urlretrieve(url, filepath)
          break
        except:
          retry += 1
      count += 1
      print filename
    start += len(result)

def search(start, keyword):
  #yahoo_web = "http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch?"
  yahoo_img = "http://api.search.yahoo.co.jp/ImageSearchService/V1/imageSearch?"
  field = {"appid":"********",
      "query":keyword.encode('utf8'),
      "results":"10",
      "adult_ok":"1",
      "type":"all",
      "start": "%d" % start,
      "format":"any"}
  request = yahoo_img + urllib.urlencode(field)
  url = urllib.urlopen(request)
  data = url.read()
  url.close()
  
  """
  # オブジェクトとして扱う場合
  tree = objectify.fromstring(data)
  print tree.get("totalResultsReturned")
  for e in tree.Result:
    print e.Url, e.Title
  url_list = [e.Url for e in tree.Result]
  """
  
  # XPathで扱う場合
  tree = etree.fromstring(data)
  if tree.tag.find("Error") != -1:
    print data
    raise Exception
  ns = [e.split()[0] for e in tree.attrib.values() if e.startswith("urn")][0]
  result = tree.xpath("//n:Result/n:Url", {'n': ns})
  url_list = [e.text for e in result]
  
  return url_list

if __name__ == '__main__':
  main()

*1:エロパワーは偉大