Граббинг Google Maps и других сервисов

Захотелось мне недавно повесить на стену постер со спутниковым снимком. Выбрав локацию на Google Maps (аэропорт Сиднея) и формат постера (A1, 841 × 1189 мм, 9932 x 7023 @ 300 dpi), начал искать граббер. Попробовал несколько вариантов, но у всех была одна проблема — они запрашивали изображения напрямую, поэтому через несколько десятков запросов Google банил мой IP (первый раз на 15 минут, потом на несколько дней).
Так как граббер сам по себе очень простой, а проблема бана граббинга свойственна не только Google Maps, решил написать небольшой скрипт, решающий эту проблему.
Итак, задачу удалось решить следующим образом (ОС Ubuntu):
Устанавливаем и настраиваем связку TOR+Privoxy (инструкция). TOR — сеть анонимных прокси, пропускающая ваш трафик через несколько серверов, расположенных в разных странах. Нам анонимность не нужна, зато возможность менять IP будет полезной. А Privoxy — обычный прокси-сервер, который будет перенаправлять наши HTTP-запросы на SOCKS-порт локально сервера TOR.
В конфигурации TOR (/etc/tor/torrc) убираем комментарий перед 55-ой строкой «ControlPort 9051» и перезапускаем сервер, чтобы иметь возможность рулить TOR'ом по телнету. По умолчанию TOR выбирает новый IP только при запуске.
Работоспособность этой системы можно проверить прописав в браузере HTTP-прокси localhost:8118 (работает довольно медленно). А также подключившись по телнету к localhost:9051 (должен открыться сеанс).
Google Maps выдает изображения блоками 256х256 пикселей, нам нужно запросить их и сложить в один файл. Номера изображений и номер масштаба можно посмотреть firebug'ом в разделе Net. Там будут вот такие ссылки:
khm1.google.com/kh/v=50&x=482397&y=314745&z=19&s=Galileo
Граббер запрашивает последовательно нужные изображения, а когда текущий IP попадает в бан, подключается к TOR и запрашивает смену прокси.
Перед запуском скрипта необходимо выполнить команду:
export http_proxy=http://127.0.0.1:8118/
Собственно код граббера, написанный на Python:
# -*- coding: utf-8 -*-
import urllib
import time
import os
import telnetlib
from PIL import Image
# Параметры
x = 482289
y = 314715
w = 3
h = 3
z = 19
v = 43
filename = 'result.jpg'
# Константы
iw = 256
ih = 256
# Создаем изображение нужного размера.
im = Image.new('RGB', (w * iw, h * ih))
# Скачиваем каждый блок и помещаем на общее изображение.
for i in range(w):
for j in range(h):
attempts = 0
while attempts < 30:
attempts += 1
print str(i) + ', ' + str(j) + ' (' + str(attempts) + ')' + \
' http://khm0.google.com/kh/v=' + str(v) + '&x=' + str(i + x) + \
'&y=' + str(j + y) + '&z=' + str(z)
try:
# Запрашиваем картинку с Google.Maps и сохраняем во временный файл.
google = urllib.urlopen('http://khm0.google.com/kh/v=' + str(v) + '&x=' + \
str(i + x) + '&y=' + str(j + y) + '&z=' + str(z))
tmp_file = open('tmp.jpg', 'wb')
tmp_file.write(google.read())
tmp_file.close()
tmp = Image.open('tmp.jpg')
except Exception:
# Если не получилось скачать больше 3 раз,
# подключаемся по телнету к локальному серверу TOR
# и запрашиваем прокси с другим IP.
if attempts > 3:
tn = telnetlib.Telnet('127.0.0.1', 9051)
tn.read_until("Escape character is '^]'.", 2)
tn.write("AUTHENTICATE\r\n")
tn.read_until("250 OK", 2)
tn.write("signal NEWNYM\r\n")
tn.read_until("250 OK", 2)
tn.write("quit\r\n")
tn.close()
# Ждем 3 секунды
time.sleep(3)
else:
im.paste(tmp, (i * iw, j * ih))
# Сохраняем результат в конце каждой полосы.
if j == h - 1:
im.save(filename, 'JPEG')
break
# Удаляем временный файл.
os.remove('tmp.jpg')
Работает он медленно, но верно :) Заменив часть кода, связанную с Google Maps, можно использовать код для граббинга любого другого сервиса, ограничивающего количество запросов. В мирных целях конечно же.
А вот и результат:

Если что, вот скачанный файл (15360 х 11008 пикс., 37 МБ).
UPD: Основная цель была — обойти ограничение, а не слить снимок…



комментарии (137)