Парсинг картинок из выдачи: фильтры Яндекса, Google и Bing
· парсинг · картинки
Поиск по картинкам — отдельная выдача со своими правилами: другая разметка, другой размер страницы, другая пагинация и свой набор фильтров у каждого поисковика. Собирают её ради разного: проверить, откуда расходятся ваши изображения, найти оригинал по теме, набрать обучающую выборку, посмотреть, чьи картинки поисковик считает подходящими под запрос.
Ниже — что в трёх поисковиках устроено одинаково (и потому вынесено в общие параметры), а что у каждого своё и задаётся его собственными фильтрами. Методы: /api/yandex/images, /api/google/images и /api/bing/images.
Одна форма ответа на три поисковика
Карточку картинки все трое описывают одними и теми же вещами, но по-разному: где-то страница-источник отдельным полем, где-то только её домен, где-то размеры превью, а где-то их нет. Мы приводим всё это к одному виду, поэтому разбор пишется один раз:
{
"url": "https://i.ytimg.com/vi/Fdier2UCgo0/maxresdefault.jpg",
"title": "Cats Try Not To Laugh 17 - YouTube",
"domain": "youtube.com",
"sourceUrl": "https://www.youtube.com/watch?v=Fdier2UCgo0",
"thumbnail": "https://avatars.mds.yandex.net/i?id=a5d639a87b2590663763dbdc42ee0367",
"width": 1280,
"height": 720,
"thumbnailWidth": 480,
"thumbnailHeight": 270,
"bytes": 78219
}
Первые четыре поля есть всегда и у всех трёх. Дальше начинаются различия, и они оформлены
отсутствием поля, а не пустым значением: bytes и размеры превью называет только
Яндекс, а Bing не всегда называет размер оригинала. Ноль вместо неизвестной ширины читался бы
как картинка нулевого размера, поэтому в таком случае поля просто нет.
Два поля стоит различать с самого начала. url — это адрес самого файла на
сайте-источнике, его качают. sourceUrl — страница, на которой картинка
стоит, на неё ссылаются. А domain — домен именно страницы-источника, а не
CDN, откуда файл раздаётся: по нему отвечают на вопрос «кто это опубликовал», и он часто не
совпадает с хостом в url.
thumbnail — превью на серверах самого поисковика. Оно живёт дольше оригинала
и отдаётся кому угодно, тогда как оригинал нередко закрыт от хотлинка: если картинки нужно
показывать у себя, брать стоит именно превью. У Google есть особенность — первые карточки
страницы приезжают превью прямо байтами (data:image/png;base64,…), и на них
уходит заметная часть веса ответа.
Общие фильтры: одно имя на три поисковика
Размер, ориентация, цвет, тип, формат файла, свежесть и сайт есть в том или ином виде у всех трёх. Задаются они общими именами, одинаково для любого поисковика:
https://jsonseo.ru/api/yandex/images?key=ВАШ_КЛЮЧ&text=котики&size=large&orientation=horizontal&format=png
https://jsonseo.ru/api/google/images?key=ВАШ_КЛЮЧ&q=котики&size=large&orientation=horizontal&format=png
https://jsonseo.ru/api/bing/images?key=ВАШ_КЛЮЧ&q=котики&size=large&orientation=horizontal&color=mono
Один и тот же orientation=vertical уходит Яндексу как iorient=vertical,
Google — как tbs=iar:t, Bing — как qft=+filterui:aspect-tall.
Полный список значений — в документации.
Чего у поисковика нет — то ошибка, а не тишина
Совпадение неполное, и это главное, что стоит знать про общие фильтры. Bing не отбирает
картинки по формату файла (кроме gif — он у него выбирается типом
«анимированный GIF»); у Яндекса нет ни розового с коричневым в цветах, ни прозрачного фона
в типах, а окна свежести у него свои — трое суток, неделя, две недели, месяц, и ничего шире
месяца.
В таких случаях запрос возвращает 422 с указанием, чем заменить это значение у нужного поисковика. Проверка происходит до обращения к поисковику, поэтому отказ ничего не стоит.
Отказ здесь полезнее тишины. Сами поисковики на непонятое значение фильтра не ругаются: они
молча его выбрасывают и отдают обычную нефильтрованную страницу с честным 200.
Снаружи она неотличима от отфильтрованной — та же сотня карточек, тот же вид, — а стоит
столько же. Запрос с опечаткой вроде color=rd вернул бы все цвета без единого
признака, что фильтр не сработал.
Два фильтра в одну ручку
Ещё один случай, когда приходит ошибка. У Яндекса анимация живёт не в типе изображения, а в
его формате — itype=gifan. Значит type=animated вместе с
format=png просят у него взаимоисключающего, и такой запрос отклоняется: по
ответу было бы не видно, какой из двух фильтров отброшен. То же у Bing с
type=photo&format=gif и у Google, когда общий фильтр и своя запись
tbs метят в одно место.
Расширенные фильтры: у каждого свои
Всё, чего в общем списке нет, задаётся родными параметрами поисковика. Они перечислены ниже
и уезжают в поисковик как есть, без перевода. А то, чего нет и в этих списках — например
фильтр, который поисковик добавит завтра, — задаётся сырой строкой:
tbs у Google и qft у Bing принимают любые записи и складываются с
остальным.
Яндекс
| Параметр | Значения |
|---|---|
isize |
large, medium, small; либо
wallpaper — только вместе с wp |
wp |
размер экрана для обоев: wh16x9_1920x1080 |
type |
photo, clipart, lineart,
face, demotivator |
icolor |
color, gray; либо red, orange,
yellow, cyan, green, blue,
violet, white, black |
itype |
jpg, png, gifan |
recent |
3D, 7D, 14D, 1M |
site |
домен; поддомены попадают тоже — wikipedia.org вернёт и
ru., и en. |
Три вещи, на которых легко обжечься. Анимация называется gifan, а не
gif. isize=wallpaper без wp (и наоборот) Яндекс не
отвергает — он просто ничего не делает, поэтому пара принимается только целиком. И у
recent ровно четыре значения: 1D, 30D,
2M, 12H и week выглядят разумно, но не работают —
поиск расширяется на всё время.
Страница у Яндекса — 20 картинок, и параметром это не меняется: numdoc,
rpp и прочее на размер не влияют. Глубина — 20 страниц, то есть 400 картинок на
запрос.
Все фильтры вертикали Google складывает в один параметр tbs через запятую;
порядок частей значения не имеет.
| Запись | Что делает |
|---|---|
isz:l, isz:m, isz:i |
большие, средние, значки |
isz:lt,islt:4mp |
не меньше N мегапикселей: 2mp…70mp, а также
qsvga, vga, svga, xga |
isz:ex,iszw:1024,iszh:768 |
точный размер — просьба, а не гарантия |
iar:t, xt, s, w,
xw |
вертикальные, панорама, квадрат, горизонтальные, панорама |
ic:color, ic:gray, ic:trans |
полноцветные, чёрно-белые, с прозрачностью |
ic:specific,isc:red |
конкретный цвет: 12 значений, включая pink и brown |
itp:face, photo, clipart,
lineart, animated |
тип изображения |
ift:jpg, png, gif, webp,
bmp, svg, ico, craw |
формат файла — в интерфейсе Google этого фильтра нет, но он работает |
sur:cl, sur:ol |
лицензии Creative Commons; коммерческие и другие |
qdr:d, w, m, y |
за сутки, неделю, месяц, год |
cdr:1,cd_min:1/31/2025,cd_max:12/31/2025 |
произвольный период, даты в формате M/D/YYYY |
Старые значения прав sur:f, sur:fc и sur:fmc больше не
работают — их место заняли cl и ol.
Те же фильтры Google принимает и полями формы расширенного поиска — imgsz,
imgar, imgtype, imgcolor, as_filetype.
Они работают наравне с записями tbs, так что использовать можно любую из двух
форм.
Страница у Google — сто картинок, и это заметно меняет арифметику: одна страница
/api/google/images стоит столько же, сколько страница Яндекса на 20 карточек.
num=20 размер не двигает. Смещение здесь считается сотнями:
start должен быть кратен 100.
Bing
Bing описывает все фильтры вертикали одним параметром qft — цепочкой токенов
+filterui:ручка-значение. Мы собираем его сами, но сырой qft тоже
принимается и складывается с остальным.
| Параметр | Значения |
|---|---|
imagesize |
small, medium, large,
wallpaper; либо 1920x1080 — не меньше этих сторон |
aspect |
square, wide, tall |
imagetype |
photo, clipart, linedrawing,
animatedgif, transparent |
people |
face (только лица), portrait (голова и плечи) |
license |
any, public, share,
sharecommercially, modify,
modifycommercially |
qft |
сырая цепочка токенов — для фильтра, которого здесь ещё нет |
Своего у Bing два: минимальные стороны в размере
(imagesize=1920x1080 — «не меньше этих сторон», более крупные тоже попадут) и
портрет — голова и плечи отдельно от просто лиц.
Лицензия и прозрачный фон, вопреки распространённому мнению, у Bing не эксклюзивны:
у Google это tbs=sur:cl и tbs=ic:trans, только записаны иначе.
Чего у Bing действительно нет — отбора по сайту и по формату файла.
И есть ручка, которой нет ни у кого: count — сколько карточек просить на
страницу, до 35. Это самый дешёвый параметр здесь, потому что цена считается страницами:
count=35&pages=5 даёт около 174 картинок за пять страниц вместо
разнобоя, который Bing выдаёт по своему усмотрению.
Пагинация: страница у всех своя
pages и page работают как в обычной выдаче, но «страница» здесь у каждого своего размера:
- Яндекс — 20 картинок, смещение номером страницы (
p), глубина 20 страниц - Google — 100 картинок, смещение сотнями (
start, кратно 100), глубина 20 страниц - Bing — до 35 картинок, смещение номером карточки с единицы
(
first), дальше 700-й карточки не листает
Соседние страницы у поисковиков слегка пересекаются, поэтому повторы в пределах одного
запроса отбрасываются, и результатов может оказаться меньше, чем
pages × размер страницы. Как и в обычной выдаче, несколько страниц лучше
просить одним запросом через pages, а не отдельными запросами со смещением —
подробности в статье
про параметр page.
Чем вертикаль картинок сложнее обычной выдачи
Общие беды парсинга — капчи, блокировки, постоянно меняющаяся вёрстка — разобраны в статье про парсер выдачи Яндекса. У картинок к ним добавляются свои, и неприятны они тем, что почти все молчаливые: сбор не падает с ошибкой, он продолжает отдавать правдоподобный ответ.
Пустой ответ не означает «ничего не нашлось». Поисковики пускают в вертикаль далеко не всех, и отказ приходит не ошибкой, а страницей — просто без картинок. Отличить «по запросу ничего нет» от «запрос заблокирован» по такому ответу нельзя, и сбор, который этого не различает, спокойно записывает пустоту как честный результат.
Порядок теряется незаметно. Ранжирование в выдаче картинок задаётся не тем же способом, что порядок карточек на странице, и разъезжается легко. Снаружи это не видно вовсе: те же двадцать картинок, тот же вид — только позиции перепутаны. Для мониторинга это худший вид поломки, потому что данные выглядят исправными.
Размер страницы не задаётся параметром. Сколько картинок отдаст поисковик, решает он сам, и число меняется от запроса к запросу. Расчёт «страниц столько-то, значит результатов столько-то» перестаёт сходиться, а пагинация, построенная на постоянном шаге, начинает пропускать или дублировать целые куски выдачи.
Фильтры исчезают молча. Уже упомянутое, но повторить стоит: неизвестное значение фильтра не вызывает ошибки ни у одного из трёх. Оно просто пропадает, а выдача приезжает полной — та же сотня карточек, тот же вид, и никакого признака, что искали совсем не то.
В /api/*/images все эти ловушки уже закрыты:
блокировка не приходит под видом пустой выдачи, порядок результатов сохраняется, а общий
фильтр, которого у поисковика нет, возвращает ошибку до обращения к нему — за
неотфильтрованную выдачу платить не придётся. Родные записи tbs и
qft при этом уходят как есть: что они значат, решает поисковик.
И последнее, что стоит помнить про любые фильтры картинок: фильтр сужает, но не гарантирует. Чем больше фильтров сложено вместе, тем чаще среди результатов попадается что-то, под них не подходящее. Классификацию делает поисковик, и расширение в адресе никогда не было доказательством формата. Если нужна гарантия — фильтруйте и по результатам тоже.