Рекурсивный поиск на сайте ссылок с httplib2 и BeautifulSoup

Я использую следующее, чтобы получить все внешние ссылки Javascript с веб-страницы. Как я могу изменить код для поиска не только по URL, но и по всем страницам сайта?

import httplib2
from BeautifulSoup import BeautifulSoup, SoupStrainer

http = httplib2.Http()
status, response = http.request('https://stackru.com')

for link in BeautifulSoup(response, parseOnlyThese=SoupStrainer('script')):
    if link.has_key('src'):
        if 'http' in link['src']:
            print link['src']

Первая попытка заставить его скрести две страницы глубоко внизу. Любой совет, как заставить его возвращать только уникальные URL? Как и большинство, они являются дубликатами. (обратите внимание, что все внутренние ссылки содержат слово "индекс" на сайтах, на которых мне это нужно.)

import httplib2
from BeautifulSoup import BeautifulSoup, SoupStrainer

site = 'http://www.stackru.com/'
http = httplib2.Http()
status, response = http.request(site)

for link in BeautifulSoup(response, parseOnlyThese=SoupStrainer('a')):
    if link.has_key('href'):
        if 'index' in link['href']:
            page = site + link['href']
            status, response = http.request(page)

            for link in BeautifulSoup(response, parseOnlyThese=SoupStrainer('script')):
                if link.has_key('src'):
                    if 'http' in link['src']:
                        print "script" + " " + link['src']
            for iframe in BeautifulSoup(response, parseOnlyThese=SoupStrainer('iframe')):
                print "iframe" + " " + iframe['src']

            for link in BeautifulSoup(response, parseOnlyThese=SoupStrainer('a')):
                if link.has_key('href'):
                    if 'index' in link['href']:
                        page = site + link['href']
                        status, response = http.request(page)

                        for link in BeautifulSoup(response, parseOnlyThese=SoupStrainer('script')):
                            if link.has_key('src'):
                                if 'http' in link['src']:
                                    print "script" + " " + link['src']
                        for iframe in BeautifulSoup(response, parseOnlyThese=SoupStrainer('iframe')):
                            print "iframe" + " " + iframe['src']

1 ответ

Сканирование сайтов - обширная тема. Принятие решения о том, как индексировать контент и ползти дальше вглубь сайта. Он включает в себя анализ содержимого, как это делает ваш элементарный сканер или паук. Определенно нетривиально написать бота, похожего по качеству на Google Bot. Профессиональные роботы-роботы выполняют большую работу, которая может включать

  • Мониторинг изменений, связанных с доменом, для инициирования сканирования
  • Расписание поиска по карте сайта
  • Извлечение веб-контента (что является предметом этого вопроса)
  • Получить набор ссылок для дальнейшего сканирования
  • Добавление весов или приоритетов к каждому URL
  • Мониторинг, когда сервисы с сайта отключаются

Для того, чтобы просто выполнить сканирование на определенном веб-сайте, таком как Stackru, я изменил ваш код для рекурсивного сканирования. Преобразовать этот код в многопоточный формат будет тривиально. Он использует bloomfilter, чтобы убедиться, что ему не нужно снова сканировать ту же страницу. Позвольте мне предупредить заранее, все еще будут неожиданные ловушки при выполнении сканирования. Зрелые программы для сканирования, такие как Scrapy, Nutch или Heritrix, работают намного лучше.

import requests
from bs4 import BeautifulSoup as Soup, SoupStrainer
from bs4.element import Tag
from bloom_filter import BloomFilter
from Queue import Queue
from urlparse import urljoin, urlparse

visited = BloomFilter(max_elements=100000, error_rate=0.1)
visitlist = Queue()

def isurlabsolute(url):
    return bool(urlparse(url).netloc)

def visit(url):
    print "Visiting %s" % url
    visited.add(url)
    return requests.get(url)


def parsehref(response):
    if response.status_code == 200:
        for link in Soup(response.content, 'lxml', parse_only=SoupStrainer('a')):
            if type(link) == Tag and link.has_attr('href'):
                href = link['href']
                if isurlabsolute(href) == False:
                    href = urljoin(response.url, href)
                href = str(href)
                if href not in visited:
                    visitlist.put_nowait(href)
                else:
                    print "Already visited %s" % href
    else:
        print "Got issues mate"

if __name__ == '__main__':
    visitlist.put_nowait('http://www.stackru.com/')
    while visitlist.empty() != True:
        url = visitlist.get()
        resp = visit(url)
        parsehref(resp)
        visitlist.task_done()
    visitlist.join()
Другие вопросы по тегам