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

StackOverflow https://stackoverflow.com/questions/419235

  •  03-07-2019
  •  | 
  •  

Question

Je suis à moitié tenté d’écrire le mien, mais je n’ai pas vraiment le temps de le faire pour le moment. J'ai consulté la liste Wikipedia de robots d'exploration de code source libre , 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 l'un de ces outils, je suis disposé à en entendre parler. J'ai utilisé Heritrix via son interface Web et je l'ai trouvé assez encombrant. 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!

Était-ce utile?

La solution

  • 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 basé sur Mechanize
  • BeautifulSoup + urllib2 fonctionne également très bien.
  • Scrapy ressemble à un projet extrêmement prometteur; c'est nouveau.

Autres conseils

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 de l'analyse HTML, XML, CSV et Javascript
  • Un pipeline de supports permettant de récupérer des éléments contenant des images (ou tout autre support) et de télécharger également les fichiers image
  • Prise en charge de l'extension de Scrapy en ajoutant 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 de l'agent utilisateur, de la gestion du fichier robots.txt, des statistiques, de la restriction de la profondeur d'analyse, etc.
  • Console de raclage interactive, 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 sur le mininova sur le site 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]

Consultez le HarvestMan , un robot d'exploration à plusieurs threads écrit en Python, donne également une Consultez le module spider.py .

Et ici , vous pouvez trouver des exemples de code permettant de créer un robot d'exploration Web simple. .

J'ai utilisé Ruya et je l'ai trouvé très bon.

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 beau, mais peut aider quelqu'un.

#!/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 __name__ == "__main__":
  main()

Croyez-moi, rien n’est meilleur que le 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()

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top