Хранение URL во время Spidering - PullRequest
7 голосов
/ 11 апреля 2010

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

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

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

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

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

  • один файл?
  • несколько файлов? как мне спроектировать файловую структуру?

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

Ответы [ 6 ]

9 голосов
/ 11 апреля 2010

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

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

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

7 голосов
/ 11 апреля 2010

Мне кажется, это важные аспекты:

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

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

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

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

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

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

4 голосов
/ 11 апреля 2010

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

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

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

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

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

2 голосов
/ 11 апреля 2010

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

http://try.mongodb.org/

Также есть привязки к Python:

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

1 голос
/ 11 апреля 2010

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

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

0 голосов
/ 12 апреля 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...