Skip to content

Завантажуємо внутрішні посилання для списку доменів з Common Crawl API

Є така некомерційна організація Common Crawl, чиї пошукові роботи обходять сторінки інтернету з метою занесення інформації про них до бази даних, доступ до якої є вільним для кожного. І сьогодні я розповім вам, як за допомогою bash написати сценарій оболонки, котрий користуючись Common Crawl API буде завантажувати унікальні внутрішні посилання для списку доменів.

Для початку, трохи розберемось як працює Common Crawl API. На сторінці https://index.commoncrawl.org/ є щомісячний список індексів, де цікава для нас колонка таблиці це “API endpoint”:

screenshot 1

Тобто, якщо ми бажаємо витягти дані з індексу за вересень 2020 року, нам потрібен запит до API за ось таким посиланням - https://index.commoncrawl.org/CC-MAIN-2020-40-index, але запит також має ще містити додаткові параметри, що б API знав що саме нас цікавить та в якому форматі, тож ми будемо використовувати наступні параметри - ?url=*.exception.net.ua&output=json. Перевіримо запит, аби бути впевненими, що все працює:

$ curl -s "https://index.commoncrawl.org/CC-MAIN-2020-40-index?url=*.exception.net.ua&output=json" | jq -r .url | uniq
https://exception.net.ua/post/
https://exception.net.ua/post/bash-history-search-up-down-keys/
https://exception.net.ua/post/bash-split-one-file-into-multiple-files-based-on-filter/
https://exception.net.ua/post/block-network-access-of-a-process/
...

І відразу маленьке пояснення. Ми вказали параметр url=*.exception.net.ua з ‘*.’ на початку домену, бо наc цікавлять внутрішні посилання не тільки цього домену, але і його піддоменів. Параметр output=json повідомляє Common Crawl API, що нам потрібна відповідь від сервера у форматі JSON.

Отже, тепер, коли ми навчились працювати з Common Crawl API, перед нами постає нова задача - отримати посилання для списку доменів та записати їх в один файл. При цьому посилання з одного домену повинні йти один за одним. Ми могли б скористатись для цього звичайним циклом, але це буде повільно, а посилання нам потрібні якомога швидше.

Звісно, ми будемо використовувати xargs, аби завантажувати посилання для кожного домену в окремому процесі. Це, звісно, що прискорить наш сценарій оболонки. Але тут з’являється одна проблема - як нам записувати посилання у файл у відповідному порядку? Я вирішив розв’язати цю проблему наступним чином:

  1. xargs створює процеси і кожен з них отримує один домен з файлу domains.txt.
  2. Використовуючи curl та jq процес завантажує внутрішні посилання у тимчасовий файл /tmp/$domain.list.
  3. Далі процес блокує доступ до файлу result.list іншим процесам за допомогою flock та дописує до нього дані з тимчасового файлу.
  4. Після запису даних в result.txt, процес видаляє тимчасовий файл та завершує роботу.
  5. xargs стартує новий процес поки не закінчаться домени з файлу domains.txt.

Звучить складно, проте наш сценарій буде займати лише один рядок:

cat domains.txt | xargs -I{} -n1 -P0 sh -c 'curl -s "https://index.commoncrawl.org/CC-MAIN-2020-40-index?url=*.{}&output=json" | jq .url | uniq > /tmp/{}.list; { flock -x 3; cat /tmp/{}.list >&3; } 3>> result.list; unlink /tmp/{}.list'

Так, це все… Сподіваюсь, що цей приклад допоможе вам у розв’язуванні схожих задач.

Корисне

  1. Розбиваємо файл на декілька інших файлів за фільтром
  2. Пошук по історії bash за допомогою курсорних клавіш
  3. Ізолюємо процес від доступу до мережі
  4. Імплементація unix socket клієнта до плеєра MOC
  5. Простий парсер логів HAProxy у реальному часі
  6. Аналіз даних за допомогою bash, StatsD та Grafana
  7. Оновлення BIOS на HP ProBook 4540s