Bunny downloader

Mitt första python-program laddade ner den senaste bunny-comic-stripen och presenterade den på mitt skrivbord. Jag var ganska nöjd med funktionen eftersom det gav en hel del nöje, men koden var något som skulle ha passat bättre som ett bash-script. Det var väldigt linjärt och anropade wget som ett externt program flera gånger och sedan utgick det från bunny-comic’s webb-sida som förändrades då och då så att programmet slutade fungera.

Bunny-comic, av Huw Lem Davies.

Efter att ha bekantat mig med python ett tag skrev jag om programmet för att använda python mer än externa program samt för att använda seriens rss-flöde. python är lyckligtvis fruktansvärt välutrustad med bibliotek och de två som behövs för att ladda ner och tolka ett rss-flöde är socket och xmllib. Socket används för att koppla upp sig mot servern i fråga och ladda ner rss-flödet, xmllib används för att tolka det nedladdade flödet.

Nedanstående klass skrev jag ihop för att hantera rss-flödet, det laddar ner rss-flödet och ersätter html-koder med motsvarande tecken. Vid initieringen av klassen laddas flödet ner med hjälp av en socket (inställd för att skicka data som en ström, och kommer därför bete sig ungefär som en fil). Data läses så läng det finns data kvar i strömmen och lagras i en intern sträng.

htmlCodes = {"‘":"\'", "&rsquo":"\'", "“": "\"", "”": "\"",""" : "\""}
#download feed
class rssFeed:

    host_str = ""
    path_str = ""
    #rssSock
    file = ""

    def cleanFeed(self, feed_str):
        for i,j in htmlCodes.iteritems():
            subst = re.compile(i)
            feed_str = subst.sub(j, feed_str)

        return feed_str

    def __init__(self, rssAddress):

        parts = re.split("/", rssAddress)
        if(len(parts) < 2):
            return
        self.host_str = parts[2]
        self.path_str = rssAddress[len(parts[2]) + 7:]

        print "host = " + self.host_str
        print "path = " + self.path_str

        self.rssSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.rssSock.connect((self.host_str, 80))

        self.rssSock.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (self.path_str, self.host_str))

        while 1:
            read_str = self.rssSock.recv(2048)

            self.file = self.file + read_str
            if not read_str:
                break
        self.file = self.cleanFeed(self.file)

Klassen rss_parser utökar xmllib‘s XMLParser-klass och bygger vidare med instruktioner för hur den skall tolka början/slut av de olika sektionerna. I mitt fall är det description-fältet som är mest intressant, här finns nämligen referens till bilden och bildtext. Med hjälp av reguljära uttryck plockar jag ut sökvägen till bilden i fråga och sparar undan den. Jag lagrar all data jag plockar ut i en lista så att jag kan välja vilken av de seriestripar som för tillfället finns i flödet som jag vill plocka ut.

#RSS parser
class rss_parser(xmllib.XMLParser):
    data  = ""
    title = []
    link  = []

    comic = []
    desc  = []

    def start_title(self, attr):
        self.data = ""

    def end_title(self):
#       print "TITLE", repr(self.data)
        self.title.append(self.data)

    def start_link(self, attr):
        self.data = ""

    def end_link(self):
#       print "LINK", repr(self.data)
        self.link.append(self.data)

    def start_description(self, attr):
        self.data = ""

    def end_description(self):
        exploded = re.split('\"', self.data)

        #self.desc.append = {exploded[1]:exploded[3]}
        #print "DESCRIPTION", self.data
        if(len(exploded) > 3):
#           print exploded[1], ":", exploded[3]
            self.comic.append(exploded[1])
            self.desc.append(exploded[3])

    def handle_data(self, data):
        self.data = self.data + data

    def get_strip(self, number):
        returnStrip = strip()

        if(number < len(self.title)):
            returnStrip.title = self.title[number]

            returnStrip.link        = self.link[number]
            returnStrip.comic       = self.comic[number]

            returnStrip.desc        = self.comic[number]

            return returnStrip

tyvärr skall man helst inte använda xmllib längre så jag är i färd med att undersöka SAX och se ifall jag kan lista ut hur det fungerar. Ifall någon som kan python/sockets/XML på riktigt läser det här får ni gärna kommentera och peka ut eventuella (eller kanske troliga) fel.

Etiketter: , , ,

Kommentera

Fyll i dina uppgifter nedan eller klicka på en ikon för att logga in:

WordPress.com Logo

Du kommenterar med ditt WordPress.com-konto. Logga ut / Ändra )

Twitter-bild

Du kommenterar med ditt Twitter-konto. Logga ut / Ändra )

Facebook-foto

Du kommenterar med ditt Facebook-konto. Logga ut / Ändra )

Google+ photo

Du kommenterar med ditt Google+-konto. Logga ut / Ändra )

Ansluter till %s


%d bloggare gillar detta: