Google イメージ検索だけ 403 ですか・・・

JavaGoogleYahoo!、Baidu でイメージ検索をした結果の画像 URL を抜き出すコードを書いてみた。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ImageSearchParser {
	
	private int page;
	private String prevWord;
	private String prevEngine;
	
	public static final String GOOGLE = "http://images.google.com/images?q=%1$s&start=%2$d&ndsp=%3$d";
	public static final String YAHOO = "http://image-search.yahoo.co.jp/search?ei=UTF-8&fr=top_ga1_sa&p=%1$s&b=%2$d&d=%3$d";
	public static final String BAIDU = "http://image.baidu.com/i?ct=201326592&cl=2&lm=-1&tn=baiduimage&pv=&word=%1$s&z=0&rn=21&pn=%2$d&ln=2000";
	
	private static String[] parse(String html) {
		Pattern pattern = Pattern.compile("\"http://[^\"]+\\.(jpg|JPG|png|PNG|gif|GIF)\"");
		Matcher m = pattern.matcher(html);
		ArrayList<String> list = new ArrayList<String>();
		while (m.find()) {
			list.add(m.group());
		}
		String[] images = new String[list.size()];
		for (int i = 0; i < images.length; i++) {
			String s = list.get(i);
			images[i] = s.substring(0, s.length() - 1).substring(1);
		}
		return images;
	}
	
	private void setEngineStatus(String engine, String word) {
		if (engine.equals(prevEngine) && word.equals(prevWord)) {
			page++;
		} else {
			prevEngine = engine;
			prevWord = word;
			page = 0;
		}
	}
	
	private String[] fromSearchEngine(URL url) throws IOException {
		URLConnection conn = url.openConnection();
		BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		StringBuffer sb = new StringBuffer();
		while (true) {
			String line = br.readLine();
			if (line == null ) {
				break;
			}
			sb.append(line);
		}
		br.close();
		return parse(new String(sb));
	}
	
	public String[] fromYahoo(String word) throws IOException {
		setEngineStatus(YAHOO, word);
		String query = String.format(YAHOO, URLEncoder.encode(word, "UTF-8"), page, 24);
		URL url = new URL(query);
		return fromSearchEngine(url);
	}
	
	public String[] fromGoogle(String word) throws IOException {
		setEngineStatus(GOOGLE, word);
		int start = page * 20;
		int count = (page + 1) * 20;
		String query = String.format(GOOGLE, URLEncoder.encode(word, "UTF-8"), start, count);
		URL url = new URL(query);
		return fromSearchEngine(url);
	}
	
	public String[] fromBaidu(String word) throws IOException {
		setEngineStatus(BAIDU, word);
		int start = (page + 1) * 16;
		String query = String.format(BAIDU, URLEncoder.encode(word, "UTF-8"), start);
		URL url = new URL(query);
		return fromSearchEngine(url);
	}
	
	public static void main(String[] args) {
		ImageSearchParser parser = new ImageSearchParser();
		try {
			for (int i = 0; i < 20; i++) {
//				String[] images = parser.fromYahoo("ガンダム");
				String[] images = parser.fromGoogle("ガンダム");
//				String[] images = parser.fromBaidu("ガンダム");
				for (String image : images) {
					System.out.println(image);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

Android でデモみたいな感じで使いたいので Google が適しているんだけど、なぜか Google は URLConnection からアクセスすると 403 を返す。他の検索エンジンで試してみたら、問題なく抽出できた。Google 側の問題(というか制限)っぽくて、調べるの面倒だな・・・。

Yahoo! を使うぐらいなら、画像共有サイトを使ったほうがよっぽどいい。でもそうすると、デモとしての公平さがなくなってしまうような気がする。やっぱり Google で何でダメなのか調べてみよう。さすがに GoogleJava で実装したブラウザからはアクセスを受け付けない、なんてことはないと思うから、何か方法があるはず、きっと。