[PYTHON]A simple web crawler.
Η ιδέα μου ήρθε καθώς διάβαζα μία συνέντευξη του Dries Buytaert, founder του Drupal. Σε κάποιο σημείο είπε πως είχε φτιάξει ένα web crawler και μαζευε στατιστικά από διάφορες ιστοσελίδες.
So… why not ;)
Με την ευκαιρία είπα να δω λίγο και την python (βασικά είναι το 1ο μου script σε python) οπότε αν έχω κάνει κάποια πατάτα, διορθώστε ελεύθερα.
Η κύρια λειτουργία του είναι να βρίσκει όλα τα links σε μία σελίδα, να τα αποθηκεύει και στην συνέχεια να τα ακολουθεί.
Αρχικά παίρνει τα “feed” urls από ένα αρχείο με όνομα urls (θα βρίσκεται στον ίδιο φάκελο). Σε κάθε νέο host, καλείται η urllib2.info() και παίρνουμε κάποιες πληροφορίες.
#!/usr/bin/env python
import urllib2, re, sys, urlparse
#******************************** Options ********************************#
def options():
print "A simple web crawler by mpekatsoula."
print "Options:"
print "-h : print help."
print "-n i : i is the number of \"crawls\" you want to do."
print " Enter -1 or leave blank for inf."
print "-o name : the name of the file you want to store the results."
print " If blank the file will be named results."
exit(0)
#************************************************************************#
# Standar values
crawls = -1
results_file = "results"
# Check user input
for arg in sys.argv[1:]:
if arg.lower()=="-h":
options()
if arg.lower()=="-n":
crawls = sys.argv[int(sys.argv[1:].index(arg))+2]
crawls = int(crawls)
if arg.lower()=="-o":
results_file = sys.argv[int(sys.argv[1:].index(arg))+2]
results_file = str(results_file)
# Open the file with the 'feed' urls
feed_urls = open('urls','r')
# Create the file to store the results
results = open(results_file,'a')
# Array that holds the urls to crawl/urls that are crawled/hosts that info has gathered
nexttocrawl = set([])
crawled_urls = set([])
gathered_info = set([])
# We need to have the expressions of a url.
# So we make an object that holds these expressions
# More info for regular expressions in python here: http://docs.python.org/dev/howto/regex.html
expressions = re.compile('<a\s*href=[\'|"](.*?)[\'"].*?>')
# Add the feed urls from the file to the array
for line in feed_urls:
nexttocrawl.add(line)
# Simple counter
i=0
while i!=crawls:
i=i+1
try:
# Get next url and print it. If the array is empty, exit.
crawling_url = nexttocrawl.pop()
print "[*] Crawling...: " + crawling_url
except KeyError:
exit(0)
# "Break" the url to components
parsed_url = urlparse.urlparse(crawling_url)
# Open the url
try:
url = urllib2.urlopen(crawling_url)
except:
continue
# Read the url
url_message = url.read()
# Find the new urls
gen_urls = expressions.findall(url_message)
# Store the crawled urls
crawled_urls.add(crawling_url)
# Add the new urls to array
for link in (gen_urls.pop() for _ in xrange(len(gen_urls))):
if link.startswith('/'):
link = 'http://' + parsed_url[1] + link
elif link.startswith('#'):
link = 'http://' + parsed_url[1] + parsed_url[2].rstrip("\n") + link
elif not link.startswith('http'):
link = 'http://' + parsed_url[1] + '/' + link
if link not in crawled_urls:
nexttocrawl.add(link)
if parsed_url[1] not in gathered_info:
gathered_info.add(parsed_url[1])
# Collect the info
collected_info = str(url.info())
# Here we store the results ;)
results.write("!!!!"+parsed_url[1]+"!!!!\n")
results.write(collected_info)
results.write("*********************************\n")
#close the files & exit
feed_urls.close()
results.close()
exit(0)
http://stack0verflow.wordpress.com/
mpekatsoula@mpekatsospito:~/Desktop$ python crawl.py -o test.out -n 10 [*] Crawling...: http://stack0verflow.wordpress.com/ [*] Crawling...: http://avalonstar.com [*] Crawling...: http://stack0verflow.wordpress.com/about/ [*] Crawling...: http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory [*] Crawling...: http://duartes.org/gustavo/blog/category/linux [*] Crawling...: http://en.wikipedia.org/wiki/Marcelo_Tosatti [*] Crawling...: http://lxr.linux.no/linux+v2.6.28.1/arch/x86/mm/fault.c#L692 [*] Crawling...: http://www.cloudknow.com/2009/01/daily-links-18/ [*] Crawling...: http://mirror.href.com/thestarman/asm/debug/Segments.html [*] Crawling...: http://www.newegg.com/Product/Product.aspx?Item=N82E16817371005
test.out:

gratz, very nice my friend.. :D i didn’t know that you have blog, i will add you at my blogroll!
r1nu-
Hello my friend!! :P Yea, i decided to make one. Nothing special ;) Thanks mate! Waiting for the 0×375 0×03 to see u there :P!
kalo fenetai genika, alla an 8es kati apodotiko kai pou kanei douleia sto real world tote prepei mallon na ftiakseis kapoia pragmatakia ;) auto de 8a doulepsei px sto parakatw gt meta to <a den uparxei mono whitespace, alla an baleis .*? pi8anotata na mh doulepsei opws 8es, 8a briskei to prwto <a kai to teleutaio href :P pera apo auto, kalo 8a htan na xrhsimopoihseis kapoiou eidous multiplexing/demultiplexing stis sundeseis, gt me mia mono sundesh argei opws kai na to kaneis. de s lew na pas gia dos, alla kati kalutero apo 1 sundesh ;) auta..
auto de 8a doulepsei ennow to regex* , de to perase to wordpress
Για το regex δεν πολυκατάλαβα τι εννοείς (τα έβγαλε λίγο μπάχαλο μου φαίνεται..)
Όσο για πολλαπλές συνδέσεις κλπ, ναι θα ήταν αρκετά καλύτερο έτσι, αλλά όταν το έφτιαξα δεν το είδα σαν σοβαρό tool να πω την αλήθεια. Κυρίως να πάρει μια ιδέα κάποιος ;)
Thanks for the comments :P