xkcd arşivi, python, threading

Yıllardır XKCD arşivine tam olarak göz atamadım, bugün aşağıdaki diyaloğu -tekrardan- görünce artık vaktinin geldiğini anladım. [buraya random gülüş gelecek]

tüm arşivi indirmeye karar verince, yapmam gereken işlemin basit olduğunu gördüm, ama 700 küsür resmi tek thread/tek process çalışan bir python scriptiyle indirmek uzun sürecekti. bunun üstüne python’da thread pool mevzusunu hem öğrenmek hem de etinden suyundan faydalanmak için araştırdım ve çok kısa bir sürede hallettim. (akabinde python’a yine aşık oldum, tekrardan. literally.)

aşağıdaki betik threading kütüphanesi yardımıyla -biraz daha hızlıca- XKCD arşivini download ediyor. çalışması için sadece ilgili makinede python kurulu olması yeterli.

#!/usr/bin/env python
import Queue
import threading
import urllib
import re, os
 
"""
 XKCD dumper - http://www.xkcd.com
 emre yilmaz - www.darkbrown.org
"""
 
class Fetcher(threading.Thread):
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue
        self.__control_download_path()
 
    def run(self):
        while True:
            comic_id = self.queue.get()
            try:
                url    = "http://www.xkcd.com/%s/" % comic_id
                source = urllib.urlopen(url).read()
                image  = self.retrieve_image_url(source)
                self.download_image(image, comic_id)
                print "downloading image: %s" % comic_id
            except Exception, error:
                print "image cannot be retrived for this id: %s" % comic_id
 
            # birinci belli, ikinci kim?
            self.queue.task_done()
 
    def retrieve_image_url(self, source):
        try:
            reply = re.findall("(http://imgs.xkcd.com/.*)</h3>", source)[0]
        except:
            print error
            reply = ""
 
        return reply
 
    def __get_extension(self, image_url):
        return re.findall("\.[a-z]{3,4}$", image_url)[0]
 
    def __control_download_path(self):
        if not os.path.isdir(XKCD.DOWNLOAD_DIR):
            os.mkdir(XKCD.DOWNLOAD_DIR)
 
    def download_image(self, comic_url, comic_id):
        extension     = self.__get_extension(comic_url)
        image_content = urllib.urlopen(comic_url).read()
        fp = open("%s/%s%s" % (XKCD.DOWNLOAD_DIR, comic_id, extension), 'wb')
        fp.write(image_content)
        fp.close()
 
queue = Queue.Queue()
 
class XKCD(object):
 
    THREAD_COUNT = 10
    COMIC_RANGE  = 732
    DOWNLOAD_DIR = 'images'   
 
    @staticmethod
    def fetch():
        # thread'leri olustur, ve siraya diz
        for i in range(XKCD.THREAD_COUNT):
            new_thread = Fetcher(queue)
            new_thread.setDaemon(1)
            new_thread.start()
 
        # siradaki islere veriyi daya
        for item in range(1, XKCD.COMIC_RANGE):
            queue.put(item)
 
        queue.join()
 
XKCD.fetch()

1 comment

ömerJuly 25th, 2010 at 1:01 pm

tşk ederim böyle ögretici kod paylaştıgınız için.

Leave a comment

Your comment