web-dev-qa-db-fra.com

Quelqu'un connaît-il un bon robot d'indexation basé sur Python que je pourrais utiliser?

Je suis à moitié tenté d'écrire le mien, mais je n'ai pas vraiment assez de temps pour le moment. J'ai vu la liste Wikipedia de crawlers open source mais je préférerais quelque chose d'écrit en Python. Je me rends compte que je pourrais probablement simplement utiliser l'un des outils de la page Wikipedia et l'envelopper en Python. Je pourrais finir par le faire - si quelqu'un a des conseils à propos de ces outils, je suis disposé à en entendre parler. J'ai utilisé Heritrix via son interface Web et je l'ai trouvée assez lourde. Je n'utiliserai certainement pas une API de navigateur pour mon prochain projet.

Merci d'avance. En outre, ceci est ma première question SO!

67
Matt
  • Mécaniser est mon préféré; d'excellentes capacités de navigation de haut niveau (remplissage et soumission de formulaires très simples).
  • Twill est un langage de script simple construit sur Mechanize
  • BeautifulSoup + urllib2 fonctionne également assez bien.
  • Scrapy semble être un projet extrêmement prometteur; c'est nouveau.
56
RexE

Utilisez Scrapy .

Il s’agit d’un framework de robot Web tordu. Encore en développement intense mais ça marche déjà. A beaucoup de goodies:

  • Prise en charge intégrée pour l'analyse HTML, XML, CSV et Javascript
  • Un pipeline de supports permettant de récupérer des éléments avec des images (ou tout autre support) et de télécharger également les fichiers image.
  • Prise en charge de l'extension de Scrapy en connectant vos propres fonctionnalités à l'aide de middlewares, d'extensions et de pipelines
  • Large gamme de middlewares et d'extensions intégrés pour la gestion de la compression, du cache, des cookies, de l'authentification, de l'usurpation d'agent utilisateur, de la gestion du fichier robots.txt, des statistiques, de la restriction de la profondeur d'analyse, etc.
  • Console interactive de raclage Shell, très utile pour le développement et le débogage
  • Console de gestion Web pour surveiller et contrôler votre bot
  • Console Telnet pour un accès de bas niveau au processus Scrapy

Exemple de code permettant d’extraire des informations sur tous les fichiers torrent ajoutés aujourd’hui dans le site mininova torrent, à l’aide d’un sélecteur XPath sur le code HTML renvoyé:

class Torrent(ScrapedItem):
    pass

class MininovaSpider(CrawlSpider):
    domain_name = 'mininova.org'
    start_urls = ['http://www.mininova.org/today']
    rules = [Rule(RegexLinkExtractor(allow=['/tor/\d+']), 'parse_torrent')]

    def parse_torrent(self, response):
        x = HtmlXPathSelector(response)
        torrent = Torrent()

        torrent.url = response.url
        torrent.name = x.x("//h1/text()").extract()
        torrent.description = x.x("//div[@id='description']").extract()
        torrent.size = x.x("//div[@id='info-left']/p[2]/text()[2]").extract()
        return [torrent]
44
nosklo

Vérifiez le HarvestMan , un robot multi-thread écrit en Python, jetez également un oeil au module spider.py .

Et ici vous pouvez trouver des exemples de code pour construire un simple robot d'exploration de sites Web.

6
CMS

J'ai piraté le script ci-dessus pour inclure une page de connexion car j'en avais besoin pour accéder à un site Drupal Pas joli mais peut aider quelqu'un là-bas.

#!/usr/bin/python

import httplib2
import urllib
import urllib2
from cookielib import CookieJar
import sys
import re
from HTMLParser import HTMLParser

class miniHTMLParser( HTMLParser ):

  viewedQueue = []
  instQueue = []
  headers = {}
  opener = ""

  def get_next_link( self ):
    if self.instQueue == []:
      return ''
    else:
      return self.instQueue.pop(0)


  def gethtmlfile( self, site, page ):
    try:
        url = 'http://'+site+''+page
        response = self.opener.open(url)
        return response.read()
    except Exception, err:
        print " Error retrieving: "+page
        sys.stderr.write('ERROR: %s\n' % str(err))
    return "" 

    return resppage

  def loginSite( self, site_url ):
    try:
    cj = CookieJar()
    self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))

    url = 'http://'+site_url 
        params = {'name': 'customer_admin', 'pass': 'customer_admin123', 'opt': 'Log in', 'form_build_id': 'form-3560fb42948a06b01d063de48aa216ab', 'form_id':'user_login_block'}
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    self.headers = { 'User-Agent' : user_agent }

    data = urllib.urlencode(params)
    response = self.opener.open(url, data)
    print "Logged in"
    return response.read() 

    except Exception, err:
    print " Error logging in"
    sys.stderr.write('ERROR: %s\n' % str(err))

    return 1

  def handle_starttag( self, tag, attrs ):
    if tag == 'a':
      newstr = str(attrs[0][1])
      print newstr
      if re.search('http', newstr) == None:
        if re.search('mailto', newstr) == None:
          if re.search('#', newstr) == None:
            if (newstr in self.viewedQueue) == False:
              print "  adding", newstr
              self.instQueue.append( newstr )
              self.viewedQueue.append( newstr )
          else:
            print "  ignoring", newstr
        else:
          print "  ignoring", newstr
      else:
        print "  ignoring", newstr


def main():

  if len(sys.argv)!=3:
    print "usage is ./minispider.py site link"
    sys.exit(2)

  mySpider = miniHTMLParser()

  site = sys.argv[1]
  link = sys.argv[2]

  url_login_link = site+"/node?destination=node"
  print "\nLogging in", url_login_link
  x = mySpider.loginSite( url_login_link )

  while link != '':

    print "\nChecking link ", link

    # Get the file from the site and link
    retfile = mySpider.gethtmlfile( site, link )

    # Feed the file into the HTML parser
    mySpider.feed(retfile)

    # Search the retfile here

    # Get the next link in level traversal order
    link = mySpider.get_next_link()

  mySpider.close()

  print "\ndone\n"

if __== "__main__":
  main()
3
shim

J'ai utilisé Ruya et je l'ai trouvé assez bon.

3
kshahar

Croyez-moi, rien n'est meilleur que curl. le code suivant peut analyser 10 000 URL en parallèle en moins de 300 secondes sur Amazon EC2

ATTENTION: Ne touchez pas le même domaine à une vitesse aussi élevée ...

#! /usr/bin/env python
# -*- coding: iso-8859-1 -*-
# vi:ts=4:et
# $Id: retriever-multi.py,v 1.29 2005/07/28 11:04:13 mfx Exp $

#
# Usage: python retriever-multi.py <file with URLs to fetch> [<# of
#          concurrent connections>]
#

import sys
import pycurl

# We should ignore SIGPIPE when using pycurl.NOSIGNAL - see
# the libcurl tutorial for more info.
try:
    import signal
    from signal import SIGPIPE, SIG_IGN
    signal.signal(signal.SIGPIPE, signal.SIG_IGN)
except ImportError:
    pass


# Get args
num_conn = 10
try:
    if sys.argv[1] == "-":
        urls = sys.stdin.readlines()
    else:
        urls = open(sys.argv[1]).readlines()
    if len(sys.argv) >= 3:
        num_conn = int(sys.argv[2])
except:
    print "Usage: %s <file with URLs to fetch> [<# of concurrent connections>]" % sys.argv[0]
    raise SystemExit


# Make a queue with (url, filename) tuples
queue = []
for url in urls:
    url = url.strip()
    if not url or url[0] == "#":
        continue
    filename = "doc_%03d.dat" % (len(queue) + 1)
    queue.append((url, filename))


# Check args
assert queue, "no URLs given"
num_urls = len(queue)
num_conn = min(num_conn, num_urls)
assert 1 <= num_conn <= 10000, "invalid number of concurrent connections"
print "PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM)
print "----- Getting", num_urls, "URLs using", num_conn, "connections -----"


# Pre-allocate a list of curl objects
m = pycurl.CurlMulti()
m.handles = []
for i in range(num_conn):
    c = pycurl.Curl()
    c.fp = None
    c.setopt(pycurl.FOLLOWLOCATION, 1)
    c.setopt(pycurl.MAXREDIRS, 5)
    c.setopt(pycurl.CONNECTTIMEOUT, 30)
    c.setopt(pycurl.TIMEOUT, 300)
    c.setopt(pycurl.NOSIGNAL, 1)
    m.handles.append(c)


# Main loop
freelist = m.handles[:]
num_processed = 0
while num_processed < num_urls:
    # If there is an url to process and a free curl object, add to multi stack
    while queue and freelist:
        url, filename = queue.pop(0)
        c = freelist.pop()
        c.fp = open(filename, "wb")
        c.setopt(pycurl.URL, url)
        c.setopt(pycurl.WRITEDATA, c.fp)
        m.add_handle(c)
        # store some info
        c.filename = filename
        c.url = url
    # Run the internal curl state machine for the multi stack
    while 1:
        ret, num_handles = m.perform()
        if ret != pycurl.E_CALL_MULTI_PERFORM:
            break
    # Check for curl objects which have terminated, and add them to the freelist
    while 1:
        num_q, ok_list, err_list = m.info_read()
        for c in ok_list:
            c.fp.close()
            c.fp = None
            m.remove_handle(c)
            print "Success:", c.filename, c.url, c.getinfo(pycurl.EFFECTIVE_URL)
            freelist.append(c)
        for c, errno, errmsg in err_list:
            c.fp.close()
            c.fp = None
            m.remove_handle(c)
            print "Failed: ", c.filename, c.url, errno, errmsg
            freelist.append(c)
        num_processed = num_processed + len(ok_list) + len(err_list)
        if num_q == 0:
            break
    # Currently no more I/O is pending, could do something in the meantime
    # (display a progress bar, etc.).
    # We just call select() to sleep until some more data is available.
    m.select(1.0)


# Cleanup
for c in m.handles:
    if c.fp is not None:
        c.fp.close()
        c.fp = None
    c.close()
m.close()
3
codersofthedark

Une autre simple araignée Utilise BeautifulSoup et urllib2. Rien de trop sophistiqué, il suffit de lire tous les href construit une liste et va bien.

2
rytis
0