Хранение URL, в то время как Глобальный поиск

Я создал немного поискового робота в Python, который я использую для сбора URL. Я не интересуюсь содержанием. Прямо сейчас я сохраняю все посещаемые URL в наборе в памяти, потому что я не хочу, чтобы мой паук посетил URL дважды. Конечно, это - очень ограниченный способ выполнить это.

Таким образом, что лучший способ состоит в том, чтобы отслеживать мои посещаемые URL?

Я должен использовать базу данных?

  • какой? MySQL, SQLite, PostgreSQL?
  • как я должен сохранить URL? Как первичный ключ, пытающийся вставить каждый URL прежде, чем посетить его?

Или я должен записать им в файл?

  • один файл?
  • несколько файлов? как я должен разработать файловую структуру?

Я уверен, что существуют книги и много статей об этом или подобных темах. Можно ли дать мне некоторый совет, что я должен считать?

7
задан the Tin Man 25 July 2015 в 06:30
поделиться

6 ответов

Мне кажутся важными следующие аспекты:

  1. Вы не можете хранить URL-адреса в памяти, так как ОЗУ станет слишком большим
  2. Вам нужно быстрый поиск существования, по крайней мере, O (logn)
  3. Вам нужны быстрые вставки

Есть много способов сделать это, и это зависит от того, насколько большой станет ваша база данных. Я думаю, что база данных SQL может стать хорошей моделью для решения вашей проблемы.

Вероятно, все, что вам нужно, это база данных SQLite. Обычно поиск строк для проверки существования - медленная операция. Чтобы ускорить это, вы можете создать хэш CRC URL-адреса и сохранить как CRC, так и URL-адрес в своей базе данных. У вас будет индекс в этом поле CRC.

  • Когда вы вставляете: вы вставляете URL-адрес и хэш
  • Когда вы хотите выполнить поиск существования: вы берете CRC потенциально нового URL-адреса и проверяете, есть ли он уже в вашей базе данных.

Конечно, существует вероятность коллизии хэшей URL-адресов, но если 100% охват не важен для вас, вы можете получить удар из-за отсутствия URL-адреса в вашей БД в случае коллизии.

Вы также можете уменьшить количество столкновений разными способами. Например, вы можете увеличить размер вашей CRC (CRC8 вместо CRC4) и использовать алгоритм хеширования с большим размером. Или используйте CRC, а также длину URL.

7
ответ дан 6 December 2019 в 07:50
поделиться

Это зависит от масштаба паука, который вы собираетесь делать, и от типа машины, на которой вы это делаете. Предположим, что типичный URL-адрес представляет собой строку из 60 байтов или около того, набор в памяти будет занимать чуть больше 100 байтов на URL-адрес (наборы и dicts в Python никогда не могут превышать 60% по соображениям скорости). Если у вас есть 64-битная машина (и дистрибутив Python) с примерно 16 ГБ доступной оперативной памяти, вы наверняка могли бы выделить более 10 ГБ для рассматриваемого важного набора, что позволит вам легко найти около 100 миллионов URL-адресов или около того; но с другой стороны, если у вас 32-разрядная машина с 3 ГБ ОЗУ, вы явно не можете выделить больше, чем 1 ГБ для важного набора, что ограничивает вас примерно 10 миллионами URL-адресов. Sqlite мог бы помочь примерно в том же диапазоне размеров, где 32-битная машина не могла этого сделать, но щедро оснащенная 64-битная могла бы - скажем, 100 или 200 миллионов URL-адресов.

Помимо этого, я бы порекомендовал PostgreSQL, который также имеет преимущество в том, что он может работать на другом компьютере (в быстрой локальной сети) практически без проблем, что позволяет вам посвятить вашу основную машину работе с пауками. Думаю, MySQL & c тоже подойдет для этого, но мне нравится соответствие стандартам PostgreSQL и надежность ;-).Это позволило бы, скажем, без проблем создать несколько миллиардов URL-адресов (только быстрый диск или, что еще лучше, RAID-массив и, конечно, столько оперативной памяти, сколько вы можете себе позволить для ускорения работы).

Попытка сэкономить память / хранилище с помощью хэша фиксированной длины вместо URL-адресов, которые могут быть довольно длинными, - это нормально , если у вас все в порядке с случайными ложными срабатываниями, которые не позволят вам сканировать то, что фактически новый URL. Такие «коллизии» вовсе не должны быть вероятными: даже если вы используете только 8 байтов для хэша, у вас должен быть только существенный риск коллизии, когда вы просматриваете миллиарды URL-адресов («эвристика квадратного корня» для этого известная проблема).

С 8-байтовыми строками для представления URL-адресов архитектура набора в памяти должна легко поддерживать миллиард или более URL-адресов на хорошо оснащенной машине, как описано выше.

Итак, сколько примерно URL-адресов вы хотите сканировать и сколько оперативной памяти вы можете сэкономить? -)

4
ответ дан 6 December 2019 в 07:50
поделиться

Я написал много пауков. Для меня более серьезной проблемой, чем нехватка памяти, является возможность потери всех URL-адресов, которые вы уже просматривали, если код или машина выйдет из строя или вы решите, что вам нужно настроить код. Если у вас закончится оперативная память, большинство компьютеров и операционных систем в наши дни откроются, поэтому вы будете работать медленнее, но по-прежнему работать. Необходимость перестроить набор URL-адресов, собранных в течение многих часов работы, потому что он больше не доступен, может стать настоящим ударом по производительности.

Хранить в ОЗУ информацию, которую вы НЕ хотите терять, - это плохо. Очевидно, что база данных - это лучший способ на этом этапе, потому что вам нужен быстрый произвольный доступ, чтобы узнать, нашли ли вы уже URL-адрес. Конечно, поиск в памяти выполняется быстрее, но компромисс между выяснением того, КАКИЕ URL-адреса хранить в памяти, увеличивает накладные расходы. Вместо того, чтобы пытаться написать код, чтобы определить, какие URL-адреса мне нужны / не нужны, я сохраняю его в базе данных и концентрируюсь на том, чтобы мой код был чистым и поддерживаемым, а мои SQL-запросы и схемы - разумными. Сделайте свое поле URL уникальным индексом, и DBM сможет найти их в кратчайшие сроки, автоматически избегая избыточных ссылок.

Ваше соединение с Интернетом и сайтами, к которым вы обращаетесь, вероятно, будет намного медленнее, чем ваше соединение с базой данных на машине во внутренней сети. База данных SQLite на том же компьютере может быть самой быстрой, хотя сама DBM не так сложна, как Postgres, который мне больше всего нравится.Я обнаружил, что размещение базы данных на другом компьютере с тем же коммутатором, что и моя машина для пауков, выполняется очень быстро; Заставить одну машину обрабатывать пауки, парсинг, а затем чтение / запись базы данных - это довольно интенсивно, поэтому, если у вас есть старый компьютер, добавьте на него Linux, установите Postgres и отправляйтесь в город. Если вам нужно больше скорости, добавьте немного дополнительной оперативной памяти. Наличие этого отдельного ящика для использования базы данных может быть очень приятным.

9
ответ дан 6 December 2019 в 07:50
поделиться

Рассмотрите ] Pickling на данный момент: Простое структурированное хранилище.

Пробег, конечно, будет отличаться, потому что, как сказали другие респонденты, вы быстро исчерпаете свою оперативную память.

0
ответ дан 6 December 2019 в 07:50
поделиться

Вы просто сохраняете URL? Вам следует взглянуть на mongoDB. Это база данных NoSQL, которую довольно легко реализовать.

http://try.mongodb.org/

У него тоже есть привязки к Python:

http://api.mongodb.org/python/1.5.2%2B/index.html

2
ответ дан 6 December 2019 в 07:50
поделиться

Поскольку вполне вероятно, что вы увидите похожие URL-адреса в аналогичное время (например, при просмотре веб-сайта вы увидите множество ссылок на главную страницу веб-сайта), я бы посоветовал это вы сохраняете URL-адреса в словаре до тех пор, пока ваша память не станет ограниченной (просто жестко закодируйте разумное число, например 10M URL-адресов или подобное), а затем сбросите словарь в файл базы данных CDB , когда он станет слишком большим.

Таким образом, большинство ваших проверок URL будут в памяти (что быстро), в то время как те, которых нет в памяти, по-прежнему потребуют всего 1-2 чтения с диска, чтобы убедиться, что вы их посетили.

1
ответ дан 6 December 2019 в 07:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: