Кто-нибудь знает хороший веб-искатель на основе Python, который я мог бы использовать?
Я испытываю недоумение писать свои собственные, но на самом деле у меня нет достаточно времени. Я видел список Wikipedia сканеры с открытым исходным кодом, но я бы предпочел что-то написанное на Python. Я понимаю, что я мог бы, вероятно, просто использовать один из инструментов на странице Википедии и обернуть его в Python. Я мог бы это сделать - если у кого-нибудь есть какие-либо советы по поводу любого из этих инструментов, я могу рассказать о них. Я использовал Heritrix через веб-интерфейс, и я нашел его довольно громоздким. Я определенно не буду использовать API-интерфейс браузера для моего предстоящего проекта.
Спасибо заранее. Кроме того, это мой первый вопрос SO!
Ответы
Ответ 1
- Mechanize - мой любимый; отличные возможности просмотра на высоком уровне (супер-простая заполнение форм и их подача).
- Twill - это простой скриптовый язык, построенный на основе Mechanize
- BeautifulSoup + urllib2 также работает довольно хорошо.
- Scrapy выглядит чрезвычайно перспективным проектом; это новое.
Ответ 2
Используйте Scrapy.
Это фреймворк веб-искателя на основе скрутки. Все еще находится в тяжелом развитии, но он работает уже. Имеет много положительных героев:
- Встроенная поддержка для анализа HTML, XML, CSV и Javascript
- Конвейер для соскабливания элементов с изображениями (или любого другого носителя) и загрузки файлов изображений.
- Поддержка расширения Scrapy путем подключения ваших собственных функций с помощью посредников, расширений и конвейеров.
- Широкий спектр встроенных посредников и расширений для обработки сжатых данных, кеш файлов, куки файлов, аутентификация, спуфинг пользователя-агента, обработка robots.txt, статистика, ограничение глубины сканирования и т.д.
- Интерактивная консоль командной оболочки, очень полезная для разработки и отладки
- Консоль управления для мониторинга и управления вашим ботом
- Telnet-консоль для низкоуровневого доступа к процессу Scrapy.
Пример кода для извлечения информации обо всех торрент файлах, добавленных сегодня в mininova торрент-сайте, с помощью селектора XPath на HTML вернулся:
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]
Ответ 3
Проверьте HarvestMan, многопоточный веб-искатель, написанный на Python, также посмотрите на spider.py.
И здесь вы можете найти образцы кода для создания простого веб-искателя.
Ответ 4
Я использовал Ruya и нашел его довольно хорошим.
Ответ 5
Я взломал вышеприведенный script, чтобы включить страницу входа в систему, поскольку мне это нужно для доступа к сайту drupal. Не очень, но может помочь кому-то там.
#!/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()
Ответ 6
Поверьте мне, ничего лучше, чем завиток. следующий код может сканировать 10 000 URL-адресов параллельно менее чем за 300 секунд на Amazon EC2
ВНИМАНИЕ: Не удаляйте один и тот же домен с такой высокой скоростью..
#! /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()
Ответ 7
Другой простой паук
Использует BeautifulSoup и urllib2. Ничего слишком сложного, просто читает все href, строит список и идет, хотя он.
Ответ 8
pyspider.py