<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>[web]haver - Webfejlesztés blog</title><link>http://webhaver.hu/</link><description>webhaver.hu friss bejegyzések</description><language>hu</language><lastBuildDate>Mon, 04 Jan 2010 00:29:58 +0200</lastBuildDate><item><title>Röviden: Megjelentek a legfrissebb DjangoCon videók</title><link>http://webhaver.hu/2010/roviden-megjelentek-legfrissebb-djangocon-videok</link><description>&lt;p&gt;Szerző: laco&lt;/p&gt;
&lt;p&gt;Bejegyzés ideje: 2010.01.04. 0:29&lt;/p&gt;
&lt;br/&gt;

&lt;div class="body"&gt;
&lt;p&gt;Tegnapt&amp;oacute;l el&amp;eacute;rhetőek a 2009 &amp;eacute;vi &lt;a href="http://www.djangocon.org/2009/conference/schedule/"&gt;DjangoCon&lt;/a&gt; konferencia vide&amp;oacute;i.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A vide&amp;oacute;kat a&amp;nbsp;&lt;a href="http://djangocon.blip.tv"&gt;http://djangocon.blip.tv&lt;/a&gt;&amp;nbsp;c&amp;iacute;men lehet el&amp;eacute;rni. &amp;Eacute;rdemes v&amp;aacute;logatni, t&amp;ouml;bb &amp;eacute;rdekes t&amp;eacute;m&amp;aacute;r&amp;oacute;l is besz&amp;eacute;lnek az előad&amp;oacute;k,&lt;/p&gt;
&lt;p&gt;Az eddigi kedvencem...&lt;/p&gt;
&lt;br/&gt;
&lt;p&gt;&lt;embed type="application/x-shockwave-flash" width="480" height="350" src="http://blip.tv/play/AYG63XoC" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/p&gt;
&lt;/div&gt;
</description><pubDate>Mon, 04 Jan 2010 00:29:58 +0200</pubDate><guid>http://webhaver.hu/2010/roviden-megjelentek-legfrissebb-djangocon-videok</guid></item><item><title>Django ORM használata szkriptekből</title><link>http://webhaver.hu/2010/django-orm-hasznalata-szkriptekbol</link><description>&lt;p&gt;Szerző: szilveszter&lt;/p&gt;
&lt;p&gt;Bejegyzés ideje: 2010.01.03. 18:55&lt;/p&gt;
&lt;br/&gt;

&lt;div class="body"&gt;
&lt;p&gt;Eddig szinte mindegyik Django projektemn&amp;eacute;l felmer&amp;uuml;lt az az ig&amp;eacute;ny, hogy a h&amp;aacute;tt&amp;eacute;rben, az alkalmaz&amp;aacute;st&amp;oacute;l f&amp;uuml;ggetlen&amp;uuml;l kellene az adatb&amp;aacute;zissal dolgozni. Mindezt term&amp;eacute;szetesen a Django ORM-j&amp;eacute;t haszn&amp;aacute;lva, mert ha m&amp;aacute;r egyszer van egy ilyen nagyszerű eszk&amp;ouml;z&amp;uuml;nk, haszn&amp;aacute;ljuk is.&lt;/p&gt;
&lt;br/&gt;
&lt;p&gt;Vegy&amp;uuml;nk egy egyszerű p&amp;eacute;ld&amp;aacute;t:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;from myproject.myapp import MyModel

for myobject in MyModel.objects.all():
    print myobject
&lt;/pre&gt;
&lt;p&gt;A probl&amp;eacute;ma igaz&amp;aacute;b&amp;oacute;l csak az, hogy az ilyen h&amp;aacute;tt&amp;eacute;rben fut&amp;oacute; szkriptek a Django k&amp;ouml;rnyezeten k&amp;iacute;v&amp;uuml;l futnak (pl. cron-b&amp;oacute;l). A tr&amp;uuml;kk annyib&amp;oacute;l &amp;aacute;ll, hogy megmondjuk a Djang&amp;oacute;nak, melyik be&amp;aacute;ll&amp;iacute;t&amp;aacute;st haszn&amp;aacute;lja (itt t&amp;aacute;roljuk ugyanis az adatb&amp;aacute;zis el&amp;eacute;r&amp;eacute;s&amp;eacute;hez sz&amp;uuml;ks&amp;eacute;ges adatokat). Ehhez a DJANGO_SETTINGS_MODULE k&amp;ouml;rnyezeti v&amp;aacute;ltoz&amp;oacute;t kell megadnunk.&lt;/p&gt;
&lt;p&gt;Az egyik lehets&amp;eacute;ges megold&amp;aacute;s az, hogy a szkript futtat&amp;aacute;sakor &amp;aacute;tadjuk param&amp;eacute;terk&amp;eacute;nt:&lt;/p&gt;
&lt;pre&gt;    $ DJANGO_SETTINGS_MODULE=myproject.settings python myscript.py&lt;/pre&gt;
&lt;p&gt;Ha a 'myproject' modul nincs a Python el&amp;eacute;r&amp;eacute;si utak k&amp;ouml;z&amp;ouml;tt, akkor ezt is p&amp;oacute;tolnunk kell:&lt;/p&gt;
&lt;pre&gt;    $ PYTHONPATH="/teljes/eleresi/ut" DJANGO_SETTINGS_MODULE=myproject.settings python myscript.py&lt;/pre&gt;
&lt;p&gt;Mindezt mag&amp;aacute;b&amp;oacute;l a szkriptből is el tudjuk v&amp;eacute;gezni (a fenti p&amp;eacute;ldak&amp;oacute;d elej&amp;eacute;re kell besz&amp;uacute;rni):&lt;/p&gt;
&lt;pre class="prettyprint"&gt;import os
import sys

sys.path.append('/teljes/eleresi/ut')
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
&lt;/pre&gt;
&lt;p&gt;Ezut&amp;aacute;n &amp;uacute;gy futtathatjuk a szkript&amp;uuml;nket, mint b&amp;aacute;rmelyik m&amp;aacute;sikat:&lt;/p&gt;
&lt;pre&gt;    $ python myscript.py&lt;/pre&gt;
&lt;/div&gt;
</description><pubDate>Sun, 03 Jan 2010 18:55:52 +0200</pubDate><guid>http://webhaver.hu/2010/django-orm-hasznalata-szkriptekbol</guid></item><item><title>Telefonkönyv migrálása Androidra</title><link>http://webhaver.hu/2009/telefonkonyv-migralasa-androidra</link><description>&lt;p&gt;Szerző: szilveszter&lt;/p&gt;
&lt;p&gt;Bejegyzés ideje: 2009.12.29. 0:50&lt;/p&gt;
&lt;br/&gt;

&lt;div class="body"&gt;
&lt;p&gt;K&amp;ouml;r&amp;uuml;lbel&amp;uuml;l egy h&amp;oacute;nappal ezelőtt &amp;uacute;gy d&amp;ouml;nt&amp;ouml;ttem, hogy mobilplatformot v&amp;aacute;ltok: eg&amp;eacute;szen pontosan az eddigi Symbian alap&amp;uacute; telefonomat egy Androidos k&amp;eacute;sz&amp;uuml;l&amp;eacute;kre cser&amp;eacute;ltem. Egy ilyen v&amp;aacute;lt&amp;aacute;skor a legnagyobb fejt&amp;ouml;r&amp;eacute;st tal&amp;aacute;n a telefonk&amp;ouml;nyv migr&amp;aacute;ci&amp;oacute;ja okozza. Esetemben a probl&amp;eacute;m&amp;aacute;t &amp;uacute;gy k&amp;ouml;zel&amp;iacute;tettem meg, hogy a Nokia PC Suite seg&amp;iacute;ts&amp;eacute;g&amp;eacute;vel CSV form&amp;aacute;tumba export&amp;aacute;ltam a n&amp;eacute;vjegyz&amp;eacute;ket, majd azt megetettem a Google Contacts importer&amp;eacute;vel. Sajnos nem volt ilyen egyszerű a megold&amp;aacute;s, mivel az eml&amp;iacute;tett importer nem igaz&amp;aacute;n v&amp;eacute;gezte a dolg&amp;aacute;t &amp;uacute;gy, ahogyan azt szerettem volna. Term&amp;eacute;szetesen a Pythont h&amp;iacute;vtam seg&amp;iacute;ts&amp;eacute;g&amp;uuml;l, &amp;eacute;s a Google Contacts Data API-j&amp;aacute;ra t&amp;aacute;maszkodva siker&amp;uuml;lt megoldani a probl&amp;eacute;m&amp;aacute;t egy 100 soros szkripttel.&lt;/p&gt;
&lt;br/&gt;
&lt;p&gt;Elősz&amp;ouml;r is a hozz&amp;aacute;val&amp;oacute;k:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 db CSV f&amp;aacute;jl amely sorrendben az al&amp;aacute;bbi oszlopokat tartalmazza (ezt ig&amp;eacute;ny szerint lehet vari&amp;aacute;lni, de akkor a szkriptet is ehhez kell igaz&amp;iacute;tani): keresztn&amp;eacute;v, csal&amp;aacute;dn&amp;eacute;v, beoszt&amp;aacute;s, c&amp;eacute;g, sz&amp;uuml;let&amp;eacute;snap, mobilsz&amp;aacute;m, e-mail, otthoni telefon, munkahelyi telefon.&lt;/li&gt;
&lt;li&gt;Python (az Ubuntu 9.10-zel sz&amp;aacute;ll&amp;iacute;tott 2.6.4-et haszn&amp;aacute;ltam)&lt;/li&gt;
&lt;li&gt;gdata modul (http://code.google.com/p/gdata-python-client/downloads/list, a szkript &amp;iacute;r&amp;aacute;sakor az aktu&amp;aacute;lis verzi&amp;oacute;: 2.0.5)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A specifik&amp;aacute;ci&amp;oacute; nagyvonalakban valami ilyesmi volt: szeretn&amp;eacute;m tov&amp;aacute;bbra is valamennyire k&amp;uuml;l&amp;ouml;n kezelni a telefonk&amp;ouml;nyvemet a GMail-es kontaktokt&amp;oacute;l, &amp;uacute;gyhogy egy k&amp;uuml;l&amp;ouml;n csoportba gyűjt&amp;ouml;m ezeket, &amp;eacute;s csak ezt a csoportot szinkroniz&amp;aacute;lom a telefonnal. J&amp;oacute; lenne, ha a m&amp;aacute;r GMail-ben l&amp;eacute;tező kontaktokat felismern&amp;eacute;, &amp;eacute;s azokat &amp;ouml;sszefűzn&amp;eacute; a CSV f&amp;aacute;jlb&amp;oacute;l &amp;eacute;rkező adatokkal. A Google Contacts API-ban az e-mail c&amp;iacute;m az elsődleges kulcsa egy kontaktnak (eg&amp;eacute;szen pontosan egy m&amp;aacute;r l&amp;eacute;tező e-mail c&amp;iacute;mmel nem hozhatok l&amp;eacute;tre &amp;uacute;j n&amp;eacute;vjegyet), &amp;uacute;gyhogy erre fog &amp;eacute;p&amp;uuml;lni a felismer&amp;eacute;s.&lt;/p&gt;
&lt;p&gt;Nem szeretn&amp;eacute;m tov&amp;aacute;bb szapor&amp;iacute;tani a sz&amp;oacute;t, j&amp;ouml;jj&amp;ouml;n v&amp;eacute;gre a forr&amp;aacute;sk&amp;oacute;d &amp;eacute;s annak r&amp;ouml;vid magyar&amp;aacute;zata.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;#!/usr/bin/env python
# encoding: utf-8

import atom
import csv

from gdata.contacts import (ContactEntry, Email, GroupMembershipInfo,
    Organization, OrgName, OrgTitle, PhoneNumber,
    PHONE_MOBILE, REL_HOME, REL_WORK)
from gdata.contacts.service import ContactsQuery, ContactsService
from gdata.service import RequestError
&lt;/pre&gt;
&lt;p&gt;Eddig semmi meglepő: szeretn&amp;eacute;nk, ha k&amp;ouml;zvetlen&amp;uuml;l is futtathat&amp;oacute; lenne a szkript, tov&amp;aacute;bb&amp;aacute; import&amp;aacute;ljuk a megfelelő modulokat, oszt&amp;aacute;lyokat, illetve &amp;aacute;lland&amp;oacute;kat.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;COL_FIRST = 0
COL_LAST = 1
COL_JOB = 2
COL_COMPANY = 3
COL_BIRTHDAY = 4
COL_MOBILE = 5
COL_EMAIL = 6
COL_HOME = 7
COL_WORK = 8
&lt;/pre&gt;
&lt;p&gt;Itt defini&amp;aacute;lunk olvashat&amp;oacute;bb neveket a CSV &amp;aacute;llom&amp;aacute;ny k&amp;uuml;l&amp;ouml;nb&amp;ouml;ző oszlopainak a k&amp;oacute;d olvashat&amp;oacute;s&amp;aacute;g&amp;aacute;nak jav&amp;iacute;t&amp;aacute;sa &amp;eacute;rdek&amp;eacute;ben.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;class GoogleContactsImporter(object):

    def __init__(self, email, password, group_name='Phone'):
        self.gd_client = ContactsService()
        self.gd_client.email = email
        self.gd_client.password = password
        self.gd_client.source = 'Py-Contacts-Importer'
        self.gd_client.ProgrammaticLogin()

        feed = self.gd_client.GetGroupsFeed()
        for entry in feed.entry:
            if entry.title.text == group_name:
                self.group = entry
&lt;/pre&gt;
&lt;p&gt;Egy k&amp;uuml;l&amp;ouml;n oszt&amp;aacute;lyba gyűjtj&amp;uuml;k az importer funkcionalit&amp;aacute;s&amp;aacute;t, &amp;iacute;gy m&amp;aacute;shonnan is haszn&amp;aacute;lhat&amp;oacute; lesz a k&amp;eacute;sőbbiekben. Az &lt;code&gt;email&lt;/code&gt; &amp;eacute;s &lt;code&gt;password&lt;/code&gt; mezők a megfelelő Google fi&amp;oacute;khoz tartoz&amp;oacute; bejelentkez&amp;eacute;si inform&amp;aacute;ci&amp;oacute;k, a &lt;code&gt;group_name&lt;/code&gt; pedig annak a csoportnak a neve, amely szinkroniz&amp;aacute;l&amp;oacute;dik automatikusan a telefonnal.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;    def query_contact_by_email(self, email):
        start = 1
        step = 25
        iterations = 0
        more = True
        while more:
            query = ContactsQuery()
            query.start_index = start
            feed = self.gd_client.GetContactsFeed(query.ToUri())
            for entry in feed.entry:
                for email_item in entry.email:
                    if email_item.address.lower() == email.lower():
                        return entry
            more = len(feed.entry)
            start += 25
            iterations += 1
&lt;/pre&gt;
&lt;p&gt;Tudom, hogy sz&amp;ouml;rnyen n&amp;eacute;z ki ez a met&amp;oacute;dus, de sajnos nem tal&amp;aacute;ltam szebb megold&amp;aacute;st erre a probl&amp;eacute;m&amp;aacute;ra a Google Contacts API korl&amp;aacute;tozotts&amp;aacute;ga miatt. Ezt majd akkor fogjuk haszn&amp;aacute;lni, amikor egy m&amp;aacute;r l&amp;eacute;tező e-mail c&amp;iacute;mmel rendelkező kontaktot szeretn&amp;eacute;nk l&amp;eacute;trehozni, de a szolg&amp;aacute;ltat&amp;aacute;s hib&amp;aacute;t dob. Ekkor ez kikeresi a megfelelő n&amp;eacute;vjegyet, &amp;eacute;s ahhoz fogja hozz&amp;aacute;adni a megfelelő adatokat.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;    def construct_contact_from_row_data(self, row):
        new_contact = ContactEntry(title=atom.Title(text=' '.join([row[COL_FIRST], row[COL_LAST]]).strip()))
        new_contact.group_membership_info.append(GroupMembershipInfo(href=self.group.id.text))
        if row[COL_EMAIL]:
            new_contact.email.append(Email(address=row[COL_EMAIL], primary='true', rel=REL_WORK))
        if row[COL_COMPANY]:
            if row[COL_JOB]:
                new_contact.organization.append(Organization(org_name=OrgName(row[COL_COMPANY]), org_title=OrgTitle(row[COL_JOB]), primary='true', rel=REL_WORK))
            else:
                new_contact.organization.append(Organization(org_name=OrgName(row[COL_COMPANY]), primary='true', rel=REL_WORK))
        if row[COL_MOBILE]:
            new_contact.phone_number.append(PhoneNumber(text=row[COL_MOBILE], primary='true', rel=PHONE_MOBILE))
        if row[COL_HOME]:
            new_contact.phone_number.append(PhoneNumber(text=row[COL_HOME], rel=REL_HOME))
        if row[COL_WORK]:
            new_contact.phone_number.append(PhoneNumber(text=row[COL_WORK], rel=REL_WORK))

        return new_contact
&lt;/pre&gt;
&lt;p&gt;Ez a leghosszabb met&amp;oacute;dus, de el&amp;eacute;g egyszerű, amit csin&amp;aacute;l.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;    def handle_conflict(self, contact):
        old_contact = self.query_contact_by_email(contact.email[0].address)
        old_contact.group_membership_info.append(GroupMembershipInfo(href=self.group.id.text))
        old_contact.title = contact.title
        old_contact.phone_number = contact.phone_number
        if contact.organization:
            old_contact.organization = contact.organization
        self.gd_client.UpdateContact(old_contact.GetEditLink().href, old_contact)
&lt;/pre&gt;
&lt;p&gt;A m&amp;aacute;r l&amp;eacute;tező n&amp;eacute;vjegy mezőit fel&amp;uuml;l&amp;iacute;rjuk a megfelelő adatokkal.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;    def create_contact(self, contact):
        try:
            self.gd_client.CreateContact(contact)
        except RequestError, e:
            if e[0]['status'] == 409:
                self.handle_conflict(contact)
&lt;/pre&gt;
&lt;p&gt;Ezzel a met&amp;oacute;dussal teljes a k&amp;eacute;p: ez hivatott a l&amp;eacute;trehozott n&amp;eacute;vjegy objektumb&amp;oacute;l t&amp;eacute;nyleges n&amp;eacute;vjegyet var&amp;aacute;zsolni.&lt;/p&gt;
&lt;p&gt;V&amp;eacute;g&amp;uuml;l pedig &amp;iacute;gy tudjuk lefuttatni az import&amp;aacute;l&amp;aacute;st:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;if __name__ == '__main__':
    importer = GoogleContactsImporter()
    contact_reader = csv.reader(file('nokia_contacts_exported.csv'))
    for row in contact_reader:
        print "Processing %s..." % ' '.join([row[COL_FIRST], row[COL_LAST]]).strip()
        contact = importer.construct_contact_from_row_data(row)
        importer.create_contact(contact)
&lt;/pre&gt;
&lt;p&gt;Hivatkoz&amp;aacute;sok:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://code.google.com/apis/contacts/"&gt;Google Contacts API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/apis/contacts/docs/1.0/developers_guide_python.html"&gt;Developer's Guide: Python (Google Contacts Data API)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/apis/contacts/docs/1.0/reference.html"&gt;Reference Guide v1.0 (Google Contacts Data API)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/apis/gdata/docs/1.0/elements.html#gdContactKind"&gt;Common Elements: "Kinds" (Google Data Protocol)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</description><pubDate>Tue, 29 Dec 2009 00:50:41 +0200</pubDate><guid>http://webhaver.hu/2009/telefonkonyv-migralasa-androidra</guid></item><item><title>Számok kiírása betűkkel Python-ban</title><link>http://webhaver.hu/2009/szamok-kiirasa-betukkel-python-ban</link><description>&lt;p&gt;Szerző: laco&lt;/p&gt;
&lt;p&gt;Bejegyzés ideje: 2009.12.28. 23:45&lt;/p&gt;
&lt;br/&gt;

&lt;div class="body"&gt;
&lt;p&gt;A sz&amp;aacute;mviteli bizonylatokat &amp;eacute;s szerződ&amp;eacute;seket elő&amp;aacute;ll&amp;iacute;t&amp;oacute; alkalmaz&amp;aacute;sokban gyakran sz&amp;uuml;ks&amp;eacute;g van arra, hogy a magyar helyes&amp;iacute;r&amp;aacute;snak megfelelően betűkkel is ki tudjunk iratni egy adott &amp;ouml;sszeget vagy sz&amp;aacute;mot.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Az al&amp;aacute;bbi Python-oszt&amp;aacute;ly milli&amp;oacute;s nagys&amp;aacute;grendig &amp;eacute;s eg&amp;eacute;sz sz&amp;aacute;mokra alkalmazhat&amp;oacute;.&amp;nbsp;&lt;/p&gt;
&lt;br/&gt;
&lt;pre class="prettyprint"&gt;class Betuvel(object):
    betuvel = ''
    szam = 0.0
    
    maradek = 0
    
    EGYES = ['', 'egy', 'kettő', 'h&amp;aacute;rom', 'n&amp;eacute;gy', '&amp;ouml;t', 
             'hat', 'h&amp;eacute;t', 'nyolc', 'kilenc']
    
    TIZES = ['', 't&amp;iacute;z', 'h&amp;uacute;sz', 'harminc', 'negyven', '&amp;ouml;tven', 
             'hatvan', 'hetven', 'nyolcvan', 'kilencven']
    
    TIZEN = ['', 'tizen', 'huszon', 'harminc', 'negyven', '&amp;ouml;tven', 
             'hatvan', 'hetven', 'nyolcvan', 'kilencven']
    
    
    def __init__(self, szam=0.0):
        self.szam = szam
        if szam == 0:
            self.betuvel = 'Nulla'
        else:
            # eg&amp;eacute;sz r&amp;eacute;sz
            self.maradek = int(self.szam)
            self.betuvel = ''
            self.alakit(1000000000, 'milliard')
            self.alakit(1000000, 'milli&amp;oacute;');
            self.alakit(1000, 'ezer');
            self.alakit(1, '');
 
     
    def alakit(self, oszto=0, osztonev = ''):
        if self.maradek &amp;gt;= oszto:
            if self.betuvel:
                self.betuvel += self.kotojel()
            mit = self.maradek / oszto
            if mit &amp;gt; 100:
                self.betuvel += Betuvel.EGYES[mit / 100] + 'sz&amp;aacute;z'
            mit = mit % 100
            if mit % 10 != 0:
                self.betuvel +=  Betuvel.TIZEN[mit / 10] + Betuvel.EGYES[mit % 10] + osztonev
            else:
                self.betuvel +=  Betuvel.TIZES[mit / 10] + osztonev      
        self.maradek = self.maradek % oszto
        #return (eredmeny, maradek)
    
    def kotojel(self):    
        if self.szam &amp;gt;= 2000:
            return '-'
        else:
            return ''
    
    def elojel(self):
        if self.szam &amp;lt; 0:
            return 'minusz '
        else:
            return '' 
    
    def kiir(self):
        return self.elojel() + self.betuvel
&lt;/pre&gt;
&lt;/div&gt;
</description><pubDate>Mon, 28 Dec 2009 23:45:43 +0200</pubDate><guid>http://webhaver.hu/2009/szamok-kiirasa-betukkel-python-ban</guid></item></channel></rss>