Commoncrawl публикует список ссылок на S3. За июль 2015, например, он выглядит так:
common-crawl/crawl-data/CC-MAIN-2015-32/segments/1438042981460.12/warc/CC-MAIN-20150728002301-00000-ip-10-236-191-2.ec2.internal.warc.gz
common-crawl/crawl-data/CC-MAIN-2015-32/segments/1438042981460.12/warc/CC-MAIN-20150728002301-00001-ip-10-236-191-2.ec2.internal.warc.gz
common-crawl/crawl-data/CC-MAIN-2015-32/segments/1438042981460.12/warc/CC-MAIN-20150728002301-00002-ip-10-236-191-2.ec2.internal.warc.gz
common-crawl/crawl-data/CC-MAIN-2015-32/segments/1438042981460.12/warc/CC-MAIN-20150728002301-00003-ip-10-236-191-2.ec2.internal.warc.gz
common-crawl/crawl-data/CC-MAIN-2015-32/segments/1438042981460.12/warc/CC-MAIN-20150728002301-00004-ip-10-236-191-2.ec2.internal.warc.gz
...
По каждой ссылке доступен архив на ~800Мб, примерно такого содержания:
WARC/1.0
WARC-Type: request
WARC-Date: 2015-08-05T12:38:42Z
WARC-Record-ID: <urn:uuid:886377b3-62eb-4333-950a-85caa9a8bce8>
Content-Length: 322
Content-Type: application/http; msgtype=request
WARC-Warcinfo-ID: <urn:uuid:54b96beb-b4cc-4f71-a1bf-b83c72aac9ad>
WARC-IP-Address: 88.151.247.138
WARC-Target-URI: http://0x20.be/smw/index.php?title=Special:RecentChangesLinked&hideanons=1&target=Meeting97
GET /smw/index.php?title=Special:RecentChangesLinked&hideanons=1&target=Meeting97 HTTP/1.0
Host: 0x20.be
Accept-Encoding: x-gzip, gzip, deflate
User-Agent: CCBot/2.0 (http://commoncrawl.org/faq/)
Accept-Language: en-us,en-gb,en;q=0.7,*;q=0.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
WARC/1.0
WARC-Type: response
WARC-Date: 2015-08-05T12:38:42Z
WARC-Record-ID: <urn:uuid:17460dab-43f2-4e1d-ad99-cc8cfceb32fd>
Content-Length: 21376
Content-Type: application/http; msgtype=response
WARC-Warcinfo-ID: <urn:uuid:54b96beb-b4cc-4f71-a1bf-b83c72aac9ad>
WARC-Concurrent-To: <urn:uuid:886377b3-62eb-4333-950a-85caa9a8bce8>
WARC-IP-Address: 88.151.247.138
WARC-Target-URI: http://0x20.be/smw/index.php?title=Special:RecentChangesLinked&hideanons=1&target=Meeting97
WARC-Payload-Digest: sha1:6Z77MXWXHJYEHC75LGTN3UQMYVJAEPPL
WARC-Block-Digest: sha1:MQ4GSG7X7EU6H26SMF2NS5MADZULHOPK
WARC-Truncated: length
HTTP/1.1 200 OK
Date: Wed, 05 Aug 2015 12:31:01 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.19
X-Content-Type-Options: nosniff
Content-language: en
X-Frame-Options: SAMEORIGIN
Vary: Accept-Encoding,Cookie
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: private, must-revalidate, max-age=0
Last-Modified: Fri, 31 Jul 2015 02:16:39 GMT
Content-Encoding: gzip
Connection: close
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html>
<html lang="en" dir="ltr" class="client-nojs">
<head>
<meta charset="UTF-8" /><title>Changes related to "Meeting97" - Whitespace (Hackerspace Gent)</title>
...
Куча заголовков и с ходу ничего не понятно. Существуют специальные библиотеки для парсинга таких данных, но я использую код вида:
url_line = None
for line in sys.stdin:
if line.startswith('WARC-Target-URI'):
url_line = line
elif url_line is not None:
if 'www.google-analytics.com/analytics.js' in line:
# Strip 'WARC-Target-URI: ' and '\r\n'
yield url_line[17:-2]
Так получается раз в 10 быстрее по скорости и попроще при деплое. Можно прямо со своего компьютера запустить команду вида:
curl https://aws-publicdatasets.s3.amazonaws.com/common-crawl/crawl-data/CC-MAIN-2015-32/segments/1438044271733.81/warc/CC-MAIN-20150728004431-00294-ip-10-236-191-2.ec2.internal.warc.gz | gunzip | python grep.py
И получить список страничек с Google Analytics. Это совершенно бесплатно. Проблема только в том, что процесс займёт несколько минут и его нужно будет повторить ~30 000 раз для разных кусочков архива. Чтобы как-то ускорить расчёт обычно используют Elastic MapReduce и обрабатывают кусочки параллельно. Важно заметить, что воркеры также качают данные из S3, а не читают их из HDFS. Сколько будет стоить такое решение? Это зависит от региона и от машинок, которые будут использоваться.
С регионом понятно — нужно брать тот, который поближе к данным, то есть «Запад США». А вот с машинками непросто. Если взять совсем дешёвых будет долго считаться, если взять мощных будет дорого. Чтобы определиться, я арендовал 6 разных тачек и запустил на них команду, как в примере выше. Получилось, что на самой простой машине я смогу обрабатывать ~10 кусочков архива за час, а на самой крутой — ~1000. Умножив это на цены за аренду машин и за настройку на них MapReduce, увидел интересное: выгоднее брать самые супер пупер крутые тачки. Финальная цена получится меньше и кластер будет компактнее.
Здорово, но цена в ~70$ не радует, особенно если нужно повторить расчёт на нескольких месяцах, чтобы проследить динамику. У Амазона есть такая прекрасная штука — спот-инстансы. Цены на них значительно ниже и меняются во времени.
Самую крутую модель, которая обычно стоит 1.68$ за час, можно арендовать за ~0.3$. В чём подвох? Если найдётся, кто-то кто захочет дать больше, машину жёстко тушат, ничего не сохраняют и передают этому человеку. Чтобы погрепать интернет спот-инстансы подходят идеально. Даже если вычисления прервут, их легко возобновить. Жалко только, что за настройку MapReduce на спот-инстансах Амазон скидки не даёт:
Уже значительно лучше. Но теперь обидно платить за MapReduce ~0.3$, когда вся машина стоит ~0.3$. Особенно учитывая, что ни HDFS, ни reduce-ступень не используется. Здесь, наверное, и становится понятно, как можно сократить стоимость расчёта в два раза. Грубо говоря, нужно запилить свой MapReduce на коленочке. Для данной задачи это сделать несложно. Нужно просто написать скрипт, который всё делает сам: скачивает архив, распаковывает его и грепает. И запустить его за нескольких машинах с разными параметрами, я делал это через screen примерно так:
scp run_grep.py ubuntu@machine1:~
ssh ubuntu@machine1 -t 'screen -d -r "python run_grep.py 2015-07 0 1000"'
scp run_grep.py ubuntu@machine2:~
ssh ubuntu@machine2 -t 'screen -d -r "python run_grep.py 2015-07 1000 2000"'
scp run_grep.py ubuntu@machine3:~
ssh ubuntu@machine3 -t 'screen -d -r "python run_grep.py 2015-07 2000 3000"'
...
Если ещё немного напрячься и настроить сбор логов с машин, можно сделать себе роскошный мониторинг:
Комментарии (16)
mickvav
05.10.2015 07:16+5Если вас устраивает результат с некой погрешностью — можно ещё сделать выборку случайного подмножества, например 1000 дампов из 30000 уже буду давать неплохую точность на запросах вида 'сколько сайтов используют wordpress'
VioletGiraffe
05.10.2015 08:04+1Какая степень сжатия у архивов? 30 ТБ — не маловато ли? Мы так мало настрочили за столько лет?
Xfrid
05.10.2015 08:13Тоже интересно, этот паук дотягивается до страничек в фейсбуке и контакте?
VioletGiraffe
05.10.2015 08:21Во-во! Я не пытался оценить (можно попробовать), но не удивлюсь, если в одном только ФБ больше 30 ТБ текста.
Xfrid
05.10.2015 08:27Ну, полная коллекция флибусты в полмиллиона книг весит 388гб в сжатом виде, а там форматы не чисто текстовые, весят прилично и сжимаются хуже.
alexkuku
05.10.2015 12:16+2~5. После распаковки получается ~150Тб. Да, там не весь интернет. Они прокачивают некоторый конечный набор урлов. Что хуже всего не раскрывается, как формируется этот набор. Вроде бы, его предоставляет Blekko. По опыту могу сказать, что там находится ~10% урлов от того, что должно было найтись.
joger
05.10.2015 10:01+1проверил через urlsearch.commoncrawl.org пару доменов. либо ничего, либо только главная. хотя никаких запретов через роботс.тхт или мета. так что придётся и дальше самому :(
bkh
08.10.2015 04:20А чем вам для этой задачи не подошел apache spark? Там и скрипты для разворачивания кластера на ec2 есть, и спот инстансы можно заказать. Не говоря уже о таких штуках как автоматическое распиливание датасета c s3 и агрегация результата.
fomistoklus
можно прикрутить configuration tool (like chef or puppet) чтобы разворачивание происходило автоматически + логику написать, которая будет выдавать этому CT спот инстансы и вести учет того, что посчиталось и что должно посчитаться.