Когда-то давно передо мной стояла задача по поиску файлов на ресурсах, которые могли уже не работать или определённые данные с них были удалены. Тогда для этой цели я использовал веб архивы Common Crawl и самопальный инструмент для автоматизации взаимодействия с ним.
Сейчас мне понадобилось решить схожую задачу, но Common Crawl упал и пока не встаёт... Поэтому было принято решение допилить свой инструмент до уровня скоростного велосипеда с использованием Wayback Machine и поделиться небольшим опытом извлечения архивных данных.
Не погружаясь сильно в детали, далее, в общих чертах я опишу что используют сервисы для архивации, как мы можем этим пользоваться через API, а в конце мы сертифицируемся по-ЦРУшному используя инструмент GoGetCrawl.
Общие моменты
Для начала стоит упомянуть про общие моменты сервисов веб архивирования. Архивы хранятся в файлах WARC/ARC формата, затем с помощью CDX сервера мы можем исследовать данные файлы используя различные фильтры. Популярным инструментом, с помощью которого это осуществляется являться pywb.
Например, на скриншоте ниже можно увидеть результат запроса http://<server_addr>/cdx?url=https://twitter.com/internetarchive/
к CDX серверу:
Как видим в результате будут получены данные содержащие оригинальный URL (original
), статус при его запросе (status code
) на момент сбора данных (timestamp
), тип файла (mimetype
) и другие интересные параметры. Более детальное описание CDX сервера и используемых при запросах параметрах можно найти тут.
Помимо сервисов Wayback Machine и Common Crawl, которые мы рассмотрим далее существуют множество других. Но их архивы менее обширны и скорее носят локальный характер по стране или тематике. Некоторые из них можно посмотреть тут.
Извлекаем файлы из архивов
Думаю многие пользовались web-архивами через удобные интерфейсы. Сейчас я покажу как это сделать неудобно используя API на примере 2 популярных сервисов. К примеру мы хотим получить все JPEG файлы на cia.gov
и его поддоменах, а затем скачать интересующий нас файл.
Wayback Machine
Работаем ручками с Wayback machine
Для осуществления нашей задачи на данном ресурсе мы используем следующий запрос:
https://web.archive.org/cdx/search/cdx?url=*.cia.gov/*&output=json&limit=10&filter=mimetype:image/jpeg&collapse=urlkey
Где:
/cdx/search/cdx
- endpoint CDX сервера,url=*.cia.gov/*
- исследуемый URL,filter=mimetype:image/jpeg
- фильтрация по MIME типу JPEG файла,output=json
- требуем результат в формате JSON,limit=10
- ограничиваемся 10 результатами,collapse=urlkey
- получаем уникальные URL (без этого много дубликатов).
В результате мы получаем 10 найденных изображений в архиве. Из интересного, помимо URLов, ответ содержит MIME тип файлов (полезно если не используется фильтрация), и статус код при доступе к объекту на момент составления архива:
[["urlkey","timestamp","original","mimetype","statuscode","digest","length"],
["gov,cia)/++theme++contextual.agencytheme/images/aerial-analysis-btn.jpg", "20150324125120", "https://www.cia.gov/++theme++contextual.agencytheme/images/aerial-analysis-btn.jpg", "image/jpeg", "200", "OJRFXPWOPZQGPRIZZQZOTRSZKAVLQLKZ", "3845"],
["gov,cia)/++theme++contextual.agencytheme/images/aerial_cropped.jpg", "20160804222651", "https://www.cia.gov/++theme++contextual.agencytheme/images/Aerial_Cropped.jpg", "image/jpeg", "200", "3WII7DZKLXM4KSQ5UTEKO5EL7H5VTB35", "196685"],
["gov,cia)/++theme++contextual.agencytheme/images/background-launch.jpg", "20140121032437", "https://www.cia.gov/++theme++contextual.agencytheme/images/background-launch.jpg", "image/jpeg", "200", "3C4G73473VYPOWDNA4VJUV4Q7EC3IXN4", "44501"],
["gov,cia)/++theme++contextual.agencytheme/images/background-video-panel.jpg", "20150629034524", "https://www.cia.gov/++theme++contextual.agencytheme/images/background-video-panel.jpg", "image/jpeg", "200", "CQCUYUN5VTVJVN4LGKUZ3BHWSIXPSCKC", "71813"],
["gov,cia)/++theme++contextual.agencytheme/images/bannerheads/an-1.jpg", "20130801151047", "https://www.cia.gov/++theme++contextual.agencytheme/images/bannerheads/an-1.jpg", "image/jpeg", "200", "GPSEAEE23C53TRGHLMBXHWQYNB3EGBCZ", "14858"],
["gov,cia)/++theme++contextual.agencytheme/images/bannerheads/an-2.jpg", "20130801150245", "https://www.cia.gov/++theme++contextual.agencytheme/images/bannerheads/an-2.jpg", "image/jpeg", "200", "L6P2MNAAMZUMHUEHJFGXWEUQCHHMK2HP", "15136"],
["gov,cia)/++theme++contextual.agencytheme/images/bannerheads/an-3.jpg", "20130801151656", "https://www.cia.gov/++theme++contextual.agencytheme/images/bannerheads/an-3.jpg", "image/jpeg", "200", "ODNXI3HZETXVVSEJ5I2KTI7KXKNT5WSV", "19717"],
["gov,cia)/++theme++contextual.agencytheme/images/bannerheads/an-4.jpg", "20130801150219", "https://www.cia.gov/++theme++contextual.agencytheme/images/bannerheads/an-4.jpg", "image/jpeg", "200", "X7N2EIYUDAYWMX7464LNTHBVMTEMZUVN", "20757"],
["gov,cia)/++theme++contextual.agencytheme/images/bannerheads/banner-benefits-background.jpg", "20150510022313", "https://www.cia.gov/++theme++contextual.agencytheme/images/bannerheads/banner-benefits-background.jpg", "image/jpeg", "200", "VZJE5XSAQWBD6QF6742BH2N3HOTSCZ4A", "12534"],
["gov,cia)/++theme++contextual.agencytheme/images/bannerheads/chi-diversity.jpg", "20130801150532", "https://www.cia.gov/++theme++contextual.agencytheme/images/bannerheads/CHI-diversity.jpg", "image/jpeg", "200", "WJQOQPYJTPL2Y2KZBVJ44MVDMI7TZ7VL", "6458"]]
Далее, чтобы получить доступ к архивированному файлу, мы берем один из результатов выше и используем следующий запрос:
https://web.archive.org/web/20150324125120id_/https://www.cia.gov/++theme++contextual.agencytheme/images/aerial-analysis-btn.jpg
Где:
/web
- endpoint сервера с файлами,20230502061729id_
- timestamp полученный в предыдущем запросе + id_,https://company.habr.com/images/lanit.jpg
- url файла из предыдущего запроса.
Common Crawl
Работаем ручками с Common Crawl
В случае с данным сервисом задача немного отяжеляется тем, что он перегружен, и сейчас пользоваться CDX сервером Common Crawl крайне затруднительно. Тем не менее я опишу как это делается.
Для начала нам необходимо выбрать версию архива (Common Crawl обновляет архивы раз в месяц или два). К примеру мы выбрали версию за Март\Апрель 2023, в этом случае аналогичный запрос будет выглядеть следующим образом:
https://index.commoncrawl.org/CC-MAIN-2023-14-index?url=*.cia.gov/*&output=json&limit=10&filter=mimetype:image/jpeg&collapse=urlkey
Как и ожидалось, сервера Common Crawl на момент написания статьи всё ещё перегружены и 504 Gateway Time-out
-ают меня ?. Поэтому далее я покажу пример экстракции файла с ответом на другой запрос, который у меня есть под рукой:
{"urlkey": "com,tutorialspoint)/accounting_basics/accounting_basics_tutorial.pdf", "timestamp": "20230320100841", "url": "http://www.tutorialspoint.com/accounting_basics/accounting_basics_tutorial.pdf", "mime": "application/pdf", "mime-detected": "application/pdf", "status": "200", "digest": "2JQ2AQ3HQZIMXHB5CJGSADUGOHYBIRJJ", "length": "787172", "offset": "102849414", "filename": "crawl-data/CC-MAIN-2023-14/segments/1679296943471.24/warc/CC-MAIN-20230320083513-20230320113513-00267.warc.gz"}
{"urlkey": "com,tutorialspoint)/add_and_subtract_whole_numbers/pdf/subtracting_of_two_2digit_numbers_with_borrowing_worksheet10_1.pdf", "timestamp": "20230326185123", "url": "https://www.tutorialspoint.com/add_and_subtract_whole_numbers/pdf/subtracting_of_two_2digit_numbers_with_borrowing_worksheet10_1.pdf", "mime": "application/pdf", "mime-detected": "application/pdf", "status": "200", "digest": "T4OQARBGDQ2Z3ZMJ57MWZTUIBCFR65QG", "length": "120114", "offset": "1156945883", "filename": "crawl-data/CC-MAIN-2023-14/segments/1679296946445.46/warc/CC-MAIN-20230326173112-20230326203112-00412.warc.gz"}
{"urlkey": "com,tutorialspoint)/add_and_subtract_whole_numbers/pdf/subtracting_of_two_2digit_numbers_with_borrowing_worksheet10_2.pdf", "timestamp": "20230322123716", "url": "https://www.tutorialspoint.com/add_and_subtract_whole_numbers/pdf/subtracting_of_two_2digit_numbers_with_borrowing_worksheet10_2.pdf", "mime": "application/pdf", "mime-detected": "application/pdf", "status": "200", "digest": "EJJMOG5QPWIV7YXADIFOPML45UTJKYWW", "length": "118702", "offset": "1159004265", "filename": "crawl-data/CC-MAIN-2023-14/segments/1679296943809.76/warc/CC-MAIN-20230322114226-20230322144226-00733.warc.gz"}
{"urlkey": "com,tutorialspoint)/add_and_subtract_whole_numbers/pdf/subtracting_of_two_2digit_numbers_with_borrowing_worksheet10_3.pdf", "timestamp": "20230324124641", "url": "https://www.tutorialspoint.com/add_and_subtract_whole_numbers/pdf/subtracting_of_two_2digit_numbers_with_borrowing_worksheet10_3.pdf", "mime": "application/pdf", "mime-detected": "application/pdf", "status": "200", "digest": "AOTDOZIAULAYGY3AOMD7662BJBEPYKWJ", "length": "210009", "offset": "1172608792", "filename": "crawl-data/CC-MAIN-2023-14/segments/1679296945282.33/warc/CC-MAIN-20230324113500-20230324143500-00254.warc.gz"}
{"urlkey": "com,tutorialspoint)/adding_and_subtracting_decimals/pdf/addition_with_money_worksheet8_1.pdf", "timestamp": "20230330141211", "url": "https://www.tutorialspoint.com/adding_and_subtracting_decimals/pdf/addition_with_money_worksheet8_1.pdf", "mime": "application/pdf", "mime-detected": "application/pdf", "status": "200", "digest": "MOODQKFMHRVSZK4UOZO3E6H2MGHTK2VW", "length": "226484", "offset": "1136155166", "filename": "crawl-data/CC-MAIN-2023-14/segments/1679296949331.26/warc/CC-MAIN-20230330132508-20230330162508-00514.warc.gz"}
{"urlkey": "com,tutorialspoint)/adding_and_subtracting_decimals/pdf/addition_with_money_worksheet8_2.pdf", "timestamp": "20230330112743", "url": "https://www.tutorialspoint.com/adding_and_subtracting_decimals/pdf/addition_with_money_worksheet8_2.pdf", "mime": "application/pdf", "mime-detected": "application/pdf", "status": "200", "digest": "ZYCDOJ2JTPPWFTCNYEIXCWKEJQXTA7UD", "length": "226957", "offset": "1167440233", "filename": "crawl-data/CC-MAIN-2023-14/segments/1679296949181.44/warc/CC-MAIN-20230330101355-20230330131355-00035.warc.gz"}
Если приглядеться, то можно заметить что CDX сервер CommonCrawl возвращает нам немного другой JSON, с отличными параметрами от тех что мы видели у Wayback Machine
Теперь, для того чтобы скачать файл мы используем filename выбранного объекта на хранилище (data.commoncrawl.org):
https://data.commoncrawl.org/crawl-data/CC-MAIN-2023-14/segments/1679296949181.44/warc/CC-MAIN-20230330101355-20230330131355-00035.warc.gz
Однако перейдя по данной ссылке вместо нужного нам объекта будет скачан громоздкий скомпрессированный архив. Для получения доступа к необходимому нам файлу мы добавляем следующий заголовок к запросу Range: bytes=1170209543-1170219812
. С помощью данного заголовка мы указываем начало и конец смещения файла в архиве. Начало смещения указано в параметре offset объекта, а для вычисления конца добавляем к нему length.
В curl итоговый запрос будет выглядеть следующим образом:
curl -H "Range:bytes=1167440233-1167667190" "https://data.commoncrawl.org/crawl-data/CC-MAIN-2023-14/segments/1679296949181.44/warc/CC-MAIN-20230330101355-20230330131355-00035.warc.gz" --output test.warc.gz
В результате мы получим сжатый gzip WARC файл, декомпрессировав который мы увидим следующее содержимое:
WARC/1.0
WARC-Type: response
WARC-Date: 2023-03-30T11:27:43Z
WARC-Record-ID: <urn:uuid:23aaef68-3bb3-4849-a7b8-f81d3b6b603c>
Content-Length: 276765
Content-Type: application/http; msgtype=response
WARC-Warcinfo-ID: <urn:uuid:09066de6-1a53-44c9-80ef-921880273b06>
WARC-Concurrent-To: <urn:uuid:916a7a96-01a0-4826-acdc-77a44863736f>
WARC-IP-Address: 192.229.210.176
WARC-Target-URI: https://www.tutorialspoint.com/adding_and_subtracting_decimals/pdf/addition_with_money_worksheet8_2.pdf
WARC-Payload-Digest: sha1:ZYCDOJ2JTPPWFTCNYEIXCWKEJQXTA7UD
WARC-Block-Digest: sha1:FDUUFO3APTHN55CYNDVRD3CNPYA5NOVT
WARC-Identified-Payload-Type: application/pdf
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *;
Cache-Control: max-age=2592000
Content-Type: application/pdf
Date: Thu, 30 Mar 2023 11:27:43 GMT
Etag: "4373e-5c8329dce0d40"
Expires: Sat, 29 Apr 2023 11:27:43 GMT
Last-Modified: Wed, 28 Jul 2021 17:50:05 GMT
Server: Apache/2.4.52 (Ubuntu)
Vary: User-Agent
X-Frame-Options: SAMEORIGIN
X-Version: OCT-10 V1
X-XSS-Protection: 1; mode=block
Content-Length: 276286
%PDF-1.5
%µµµµ
<-остаток файла...->
Убрав WARC заголовки и сохранив файл, остаётся только наслаждаться скачанным нами содержимым...
GoGetCrawl и сертификат ЦРУ
Стоит сказать, что на данный момент уже существует небольшое количество инструментов для взаимодействия с архивами. Но беглым взглядом я не нашел ни одного, который помимо добычи URL, смог бы скачать файл и с лёгкостью интегрироваться в другие Go проекты!
Исходя из этого я обновил своё устаревшее решение, сделав небольшой рефакторинг и добавив Wayback Machine
в качестве второго источника архивных данных.
К делу
А теперь мы идём добывать сертификат с помощью GoGetCrawl. Использовать его можно несколькими способами, описанными тут. Не надо ничего компилировать и устанавливать, и поэтому для удобства:
Можно скачать последний релиз. И использовать бинарник следующим образом:
gogetcrawl file *.cia.gov/* --dir ./ --ext pdf
Немного подождав мы должны получить заветный файл, если ждать скучно или файла нет можно посмотреть что происходить добавив флаг -v
.
Либо использовать Docker:
docker run uranusq/gogetcrawl url *.cia.gov/* --ext pdf
В результате этой команды мы должны увидеть URL с PDF файлом. Более подробно про команды и возможные аргументы можно почитать использовав флаг -h
.
Вариант установки для Go-нщиков:
go install github.com/karust/gogetcrawl@latest
Поздравляю
Мы получили наш заветный сертификат ?. Для тех у кого его ещё нет, он выглядит следующим образом:
Так и не до конца поняв: что это и к чему оно там - я сразу поспешил поделиться этой возможностью с вами.
Опен-сорс
Для тех кто пользуется Go и хочет стать архивмагом есть возможность использования GoGetCrawl в своих проектах:
go get github.com/karust/gogetcrawl
Например, минимальная программа, которая покажет нам все страницы example.com
и его поддоменов со статусом 200 выглядит следующим образом:
package main
import (
"fmt"
"github.com/karust/gogetcrawl/common"
"github.com/karust/gogetcrawl/wayback"
)
func main() {
// Конфигурируем запрос на 10 страниц со статусом 200
config := common.RequestConfig{
URL: "*.example.com/*",
Filters: []string{"statuscode:200"},
Limit: 10,
}
// Устанавливаем таймаут и попытки для запросов
wb, _ := wayback.New(15, 2)
// Используем конфиг для взамодействия с CDX сервером
results, _ := wb.GetPages(config)
for _, r := range results {
fmt.Println(r.Urlkey, r.Original, r.MimeType)
}
}
На странице проекта есть ещё примеры использования с добычей файлов и CommonCrawl.
PS
Надеюсь никто не был закликбейчен, и все получили наслаждение от обладания новым сертификатом. Возможно существуют иные сервисы с веб-архивами, помимо описанных в статье, которые можно использовать в таком же ключе? Дайте знать в комментариях.