Приключение в обход этого надоедливого флажка.

Вы когда-нибудь встречали кого-то, кто ненавидит технологии и желает, чтобы все сотовые телефоны мгновенно прекратили свое существование? Это мой учитель математики. К счастью для всех нас, она понимает, что будущее за технологиями, нравится ей это или нет. Она решила начать публиковать материалы в Google Classroom - отличное начало. Единственная вопиющая проблема в том, что она отключила функции загрузки и печати! Не секрет, что просмотр больших PDF-файлов в браузере - медленный, утомительный и в целом мучительный процесс. Я решил, что мне нужно каким-то образом создать PDF-файл для остальной части класса, в котором не было бы проблем с навигацией.

PDF-файл или, по крайней мере, его изображения отображаются на экране. Быстрый переход на вкладку «Сеть» консоли разработчика показывает, что существуют сотни запросов к определенной конечной точке API, все из которых возвращают PNG страниц. Большой! Строка запроса API также кажется чрезвычайно простой: просто измените параметр page GET, чтобы получить другие страницы.

На этом этапе первое, что можно попробовать, - это просто перебрать страницы с 0 по 145 и загрузить все эти PNG. Большая проблема в том, что все они требуют действительных файлов cookie сеанса Google OAuth. Это означает, что использовать curl или wget для этого немного затруднительно. Я прибег к использованию только WebExtensions API. У меня уже было установлено расширение, которое я написал недавно, поэтому я просто дал ему разрешение downloads. Оттуда это простое приложение JavaScript:

function downloadPages(id, length) {
  for (let i = 0; i < length; i++) {
    browser.downloads.download({
      url: `https://drive.google.com/viewerng/img?id=${id}=&authuser=1&page=${i}&skiphighlight=true&w=2500`,
      filename: `${String(i).padStart(4, '0')}.png`
    });
  }
}

Примерно через минуту в моей папке загрузок оказалось 146 файлов PNG. Когда я попытался преобразовать в PDF, я столкнулся с несколькими ошибками.

d/Downloads/textbook
$ convert *.png out.pdf
convert: improper image header `0010.png' @ error/png.c/ReadPNGImage/4281.
convert: improper image header `0013.png' @ error/png.c/ReadPNGImage/4281.
convert: improper image header `0015.png' @ error/png.c/ReadPNGImage/4281.
convert: improper image header `0016.png' @ error/png.c/ReadPNGImage/4281.
[this goes on for a while]

Неправильные заголовки изображений? Давайте проверим шестнадцатеричный дамп одного из этих файлов.

d/Downloads/textbook
$ xxd 0010.png | head
00000000: 3c21 444f 4354 5950 4520 6874 6d6c 3e3c  <!DOCTYPE html><
00000010: 6874 6d6c 206c 616e 673d 656e 3e3c 6d65  html lang=en><me
00000020: 7461 2063 6861 7273 6574 3d75 7466 2d38  ta charset=utf-8
00000030: 3e3c 6d65 7461 206e 616d 653d 7669 6577  ><meta name=view
00000040: 706f 7274 2063 6f6e 7465 6e74 3d22 696e  port content="in
00000050: 6974 6961 6c2d 7363 616c 653d 312c 206d  itial-scale=1, m
00000060: 696e 696d 756d 2d73 6361 6c65 3d31 2c20  inimum-scale=1, 
00000070: 7769 6474 683d 6465 7669 6365 2d77 6964  width=device-wid
00000080: 7468 223e 3c74 6974 6c65 3e45 7272 6f72  th"><title>Error
00000090: 2034 3030 2028 4e6f 7420 466f 756e 6429   400 (Not Found)

Ой-ой. Похоже, Google ограничивает нас. Давайте очистим эту папку и попробуем повторно загрузить, но с небольшой задержкой между запросами. Это должно немного лучше имитировать быструю прокрутку файла. Наша последняя функция будет выглядеть примерно так:

Чтобы быть уверенным, на этот раз я запустил pngcheck для всех изображений.

d/Downloads/textbook
$ pngcheck *.png
No errors were detected in 146 of the 146 files tested.

Как только я понял, что все они ясны, все, что мне нужно было сделать, это скомпилировать PDF-файл. Проблема: у меня не было текстовых данных. Решение: tesseract-ocr, программа распознавания текста из командной строки, которая может выводить слой невидимого текста PDF. Tesseract берет список файлов из текстового файла, который достаточно легко сгенерировать с помощью find . -iname "*.png" > pnglist. Осталось только запустить OCR.

d/Downloads/textbook
$ find . -iname "*.png" > pnglist && tesseract pnglist ocr_complete -l eng pdf
Tesseract Open Source OCR Engine v4.0.0 with Leptonica
Page 0 : ./0000.png
[...]
Page 145 : ./0145.png

Полученный PDF-файл был высокого качества и с возможностью поиска. Лучше всего то, что его можно было просматривать в реальном PDF-ридере, а не в браузере. Миссия выполнена. Возьми, учитель математики.