Как спроектировать робота для сканирования? - PullRequest
5 голосов
/ 20 января 2012

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

Очевидно, мне понадобятся данные для подачи моего приложения, и я подумал, что напишу небольшой сканер, который будет занимать около 20 тыс. Страниц html и записывать их в текстовые файлы на моем жестком диске. Однако, когда я взглянул на SO и другие сайты, я не смог найти никакой информации о том, как это сделать. Это возможно? Кажется, что есть варианты с открытым исходным кодом (webpshinx?), Но я хотел бы написать это сам, если это возможно.

Схема - единственный язык, который я хорошо знаю, но я подумал, что воспользуюсь этим проектом, чтобы немного освоить Java, поэтому мне было бы интересно, есть ли какие-нибудь библиотеки ракеток или java, которые были бы полезны для этого.

Итак, я думаю, чтобы подвести итог моего вопроса, какие есть хорошие ресурсы, чтобы начать работу над этим? Как я могу заставить свой сканер запрашивать информацию с других серверов? Придется ли мне писать простой парсер для этого или это излишне, учитывая, что я хочу взять весь html-файл и сохранить его как txt?

Ответы [ 6 ]

5 голосов
/ 20 января 2012

Это вполне осуществимо, и вы определенно можете сделать это с помощью Racket.Возможно, вы захотите взглянуть на библиотеки PLaneT;В частности, HtmlPrag Нила Ван Дейка:

http://planet.racket -lang.org / display.ss? Package = htmlprag.plt & owner = neil

.. являетсяместо для начала.Вы должны иметь возможность извлекать содержимое веб-страницы в разобранный формат в одну или две строки кода.

Дайте мне знать, если у вас есть какие-либо вопросы по этому поводу.

1 голос
/ 25 января 2012

Сделав это сам в Racket, вот что я хотел бы предложить.

Начните с подхода "Unix tools":

  • Используйте curl для выполнения работызагрузка каждой страницы (вы можете выполнить ее из Racket с помощью system) и сохранение вывода во временном файле.
  • Используйте Racket для извлечения URI из тегов <a>.
    • Вы можете "обмануть" и выполнить поиск по строке регулярного выражения.
    • Или сделать это "правильным образом" с настоящим анализатором HTML, как объясняет отличный ответ Джона Клемента.
    • Подумайте, может быть сначала сделать чит, а потом вернуться назад, чтобы сделать это правильно.

На этом этапе вы можете остановиться,или вы можете вернуться и заменить curl своим собственным кодом для загрузки.Для этого вы можете использовать net/url модуль Racket.

Почему я предлагаю попробовать curl, во-первых, это то, что он помогает вам сделать что-то более сложное, чем может показаться:

  • Хотите ли вы использовать 30-кратное перенаправление?
  • Хотите ли вы принимать / хранить / предоставлять файлы cookie (в противном случае сайт может вести себя иначе)?
  • Хотите ли вы использовать HTTP keep-alive?
  • И снова и снова.

Использование, например, curl:

(define curl-core-options
  (string-append
   "--silent "
   "--show-error "
   "--location "
   "--connect-timeout 10 "
   "--max-time 30 "
   "--cookie-jar " (path->string (build-path 'same "tmp" "cookies")) " "
   "--keepalive-time 60 "
   "--user-agent 'my crawler' "
   "--globoff " ))

(define (curl/head url out-file)
  (system (format "curl ~a --head --output ~a --url \"~a\""
                   curl-core-options
                   (path->string out-file)
                   url)))

(define (curl/get url out-file)
  (system (format "curl ~a --output ~a --url \"~a\""
                  curl-core-options
                  (path->string out-file)
                  url)))

представляет собой лот кода, которыйв противном случае вам нужно было бы писать с нуля в Racket.Чтобы сделать все то, что эти curl флаги командной строки делают для вас.

Вкратце: начните с самого простого случая использования существующих инструментов.Используйте Racket почти как сценарий оболочки.Если это достаточно хорошо для вас, остановитесь.В противном случае продолжайте заменять инструменты один за другим на ваш заказ.

0 голосов
/ 29 января 2012

Я сделал это в Perl несколько лет назад (намного проще, даже без модуля webcrawler).

Я предлагаю вам прочитать документацию по wget и использовать этот инструмент для вдохновения.Wget - это netcat для веб-сканирования;его набор функций вдохновит вас.

Ваша программа должна принять список URL-адресов для начала и добавить их в список URL-адресов, чтобы попробовать.Затем вам нужно решить, хотите ли вы собирать все URL-адреса или добавлять только те из доменов (и поддоменов?), Которые указаны в первоначальном списке.

Я сделал вам довольно надежную отправную точку в схеме:

(define (crawl . urls)
  ;; I would use regular expressions for this unless you have a special module for this
  ;; Hint: URLs tend to hide in comments. referal tags, cookies... Not just links.
  (define (parse url) ...)
  ;; For this I would convert URL strings to a standard form then string=
  (define (url= x y) ...)
  ;; use whatever DNS lookup mecanism your implementation provides
  (define (get-dom) ...)
  ;; the rest should work fine on its own unless you need to modify anything
  (if (null? urls) (error "No URLs!")
      (let ([doms (map get-dom urls)])
        (let crawl ([done '()])
          (receive (url urls) (car+cdr urls)
            (if (or (member url done url=)
                      (not (member (get-dom url) doms url=)))
                (crawl urls done)
                (begin (parse url) (display url) (newline)
                  (crawl (cons url done)))))))))
0 голосов
/ 20 января 2012

На вашем месте я бы не написал сканер - я бы использовал один из многих бесплатных инструментов, которые загружают сайты локально для просмотра в автономном режиме (например, http://www.httrack.com/), чтобы сделать паутинку. Вы можетенужно настроить параметры отключения загрузки изображений и т. д., но эти инструменты будут более надежными и настраиваемыми, чем все, что вы пишете сами.

Как только вы это сделаете, у вас будет целая тонна HTMLлокальные файлы, которые вы можете передать в свое приложение.

Я провел много текстового анализа HTML-файлов: как парень из Java, я выбрал свою библиотеку для дистилляции HTML в текст (опять же, не то, что вам нужно)это отличный парсер из Jericho: http://jericho.htmlparser.net/docs/index.html

EDIT: перечитывая ваш вопрос, похоже, вы настроены на написание своего собственного сканера, в таком случае я бы порекомендовал Commons HttpClient сделатьзагрузка и еще Иерихон, чтобы вытащить ссылки и обработать их в новые запросы.

0 голосов
/ 20 января 2012

Если вы знаете схему и хотите облегчить изучение Java, почему бы вам не начать с Clojure?

Вы можете использовать свои знания lisp и использовать библиотеки разбора java html *, чтобы что-то работало. Затем, если вы хотите начать переводить его части на Java, чтобы немного узнать, вы можете написать кусочки функциональности на Java и связать их с кодом Clojure.

Удачи!

* Я видел несколько ТАК вопросов по этому вопросу.

0 голосов
/ 20 января 2012

Я предлагаю заглянуть в веб-сканер с открытым исходным кодом для Java, известный как crawler4j .

Он очень прост в использовании и предоставляет очень хорошие ресурсы и возможности для сканирования.

...