In this Article
Veriler, basit CSV tabloları ve JSON nesnelerinden daha açıklayıcı ve hiyerarşik XML belgelerine kadar farklı biçimlerde bulunur. XML biraz eski usul görünebilir, ancak RSS akışlarında, API’lerde ve yazılım yapılandırmalarında hâlâ her yerdedir.
XML verilerini kullanabilmek için önce onları ayrıştırmanız gerekir. Başka bir deyişle, programınıza içindekileri okumayı öğretirsiniz. ElementTree, minidom ve lxml gibi Python kütüphaneleriyle XML ayrıştırma açık ve sezgisel bir süreçtir.
Karşılaştığınız veri biçimi ne olursa olsun, özellikle XML olmak üzere bunlarla çalışmayı öğrenmek her geliştirici için gerekli bir beceridir. Bu rehberde XML’den veri okumayı, XML içinde gezinmeyi ve veri çıkarmayı adım adım öğreneceksiniz.
XML’in temelleri
XML, Genişletilebilir İşaretleme Dili anlamına gelir ve verileri depolamak ve taşımak için evrensel bir biçimdir. Yapısı, makinelerle uyumlu kalırken insanlar tarafından kolayca okunmasını sağlar. Bu dil, sadelik, uyarlanabilirlik ve internette geniş kullanılabilirlik odağıyla geliştirilmiştir.
XML en iyi bir ağaç olarak tanımlanabilir. Dalları ve yaprakları olan gerçek bir ağaca benzer biçimde, bir kök ve iç içe geçmiş alt öğelere sahiptir. Bu yapı, XML’in verileri hiyerarşik bir biçimde nasıl düzenlediğini gösterir. Python, XML verilerini işlemek için çeşitli yöntemler sunar; ElementTree modülü en popüler seçeneklerden biridir. ElementTree modülü, belgenin tamamını ifade eden ElementTree ve tek bir düğümü ifade eden Element olmak üzere iki temel sınıf içerir.
Geliştiriciler XML’i nasıl ayrıştırır: başlıca teknikler
Python’da, parse() işlevi genellikle XML dosyalarını işlemek için ilk adımdır. Bir XML belgesini işler ve programınızın gezinebileceği bir ağaç yapısına dönüştürür. ElementTree, lxml veya başka kütüphaneler kullanıyor olmanız fark etmeksizin bu işlev, çeşitli ayrıştırma yöntemlerinin temelini oluşturur.
Ayrıştırma yöntemlerini kavramak için önce bir XML dosyasının öğelerini bilmeniz gerekir:
- Ad alanı: öğe ve öznitelik adlarını niteleyerek ad çakışmalarını önlemeye yardımcı olur.
- Kök öğe : diğer tüm öğeleri kapsayan ana kapsayıcıdır.
- Öznitelikler : öğeler hakkında ek bilgi sağlayan anahtar-değer çiftleridir.
- Alt öğeler: verileri hiyerarşik olarak düzenleyen iç içe öğelerdir.
- Metin içeriği: öğelerde bulunan asıl bilgidir.
Bu öğeler, programların karmaşık verileri depolamasını ve paylaşmasını sağlayan yapılandırılmış bir biçim oluşturur. Yapıyı anladıktan sonra Python’daki başlıca XML ayrıştırma tekniklerini inceleyebiliriz:
1. ElementTree Modülü
XML ağaçlarını keşfetmek için kullanımı kolay bir API sunan, Python’a yerleşik bir kütüphanedir. Kullanılabilirlik ile performansı dengelediği için çoğu görevde çok iyi çalışır.
2. lxml
XPath, XSLT ve doğrulama desteği içeren üçüncü taraf bir kütüphanedir. ElementTree’den daha hızlıdır ve daha fazla özelliğe sahiptir. Karmaşık XML işleme için idealdir.
3. DOM (Belge Nesne Modeli)
Bu yöntem, XML belgesinin tamamını ağaç yapısı olarak belleğe yükler. İçinde gezinmek ve değişiklik yapmak kolay olsa da büyük dosyalarda fazla bellek kullanabilir.
4. SAX (XML için Basit API)
XML’i sıralı biçimde işleyen olay güdümlü bir ayrıştırıcıdır. Bellek kullanımı açısından verimlidir ve büyük dosyaları işlemede hızlıdır, ancak karmaşık işlemleri yönetirken daha az sezgisel olabilir.
5. Untangle
XML verilerini kolay erişim için Python nesnelerine dönüştürür. Az kodla hızlı ayrıştırma için idealdir. Ancak karmaşık XML yapılarında daha az uyarlanabilirdir.
Bu eğitim için şunlara ihtiyacınız olacak:
- Python ve requests
Bilgisayarınızda Python 3.x kurulu değilse, onu buradan indirebilirsiniz: https://www.python.org/. Bir terminal açın ve Requests’i pip kullanarak yükleyin:
pip install requests veya pip3 install requests
- Visual Studio Code (VS Code)
Gerekli tüm komutları çalıştırmak için Visual Studio Code (VS Code) içindeki terminali kullanabilirsiniz. Onu resmî web sitesinden indirip işletim sisteminiz için kurulum talimatlarını izleyin.
- RSS Akışı
RSS akışı, bir web sitesindeki haberleri veya güncellemeleri otomatik olarak iletmek için kullanılan özel bir XML dosyası biçimidir. Basitçe söylemek gerekirse, programların okuyabileceği şekilde yapılandırılmış bir tür en son gönderiler listesidir.
Örneğin, web sitemizde eğitimlerin bulunduğu bir bölüm vardır. Yeni bir eğitimin yayımlanıp yayımlanmadığını görmek için siteyi her gün kontrol etmek yerine, site son gönderilerin tümü hakkında bilgi içeren bir XML dosyası olan RSS akışı sağlar. Eğitimimizde DataImpulse RSS akışını kullanacağız. Şimdi ihtiyacımız olan kütüphanelere ve aşağıdaki koda bakalım.
ElementTree
Bir RSS akışındaki XML verilerini ayrıştırmak için Python’ın yerleşik ElementTree modülünün nasıl kullanılacağına bakalım.
İlk adım, şunu içe aktarmaktır: xml.etree.ElementTree. Süreç basittir: RSS akışı URL’sine bir GET isteği göndeririz ve sunucu XML verileriyle yanıt verir. Yanıtın .content özniteliği, ElementTree’nin ayrıştırabileceği ham bayt verisini sağlar. ET.fromstring() kullanarak bu XML metnini bir ağaç yapısına dönüştürür ve kök öğeyi alırız. İçindeki içeriğin çoğu <channel> → <item> öğeleri altında düzenlenir.
find() yöntemi ilk eşleşen öğeyi döndürürken findall() belirtilen etikete sahip tüm alt öğeleri döndürür. Burada items, her biri bir eğitimi veya makaleyi temsil eden tüm öğelerin listesidir.
Kod örneği:
import xml.etree.ElementTree as ET
import requests
# URL of the RSS feed (from DataImpulse site)
FEED_URL = "https://dataimpulse.com/tutorials-category/web-scraping-seo/feed/"
# Download the XML data
response = requests.get(FEED_URL)
xml_data = response.content
# Parse the XML
root = ET.fromstring(xml_data)
# In RSS feeds, items are inside -
channel = root.find("channel")
items = channel.findall("item")
# Print titles and links of the items
for item in items:
title = item.findtext("title")
link = item.findtext("link")
print(f"Title: {title}")
print(f"Link: {link}\n")
Son olarak, her öğenin başlığını ve bağlantısını findtext() kullanarak doğrudan metin içeriğinden çıkarır ve yazdırırız. Betiği çalıştırdığınızda, tüm eğitim başlıklarının ve URL’lerinin düzenli biçimde yazdırılmış listesini görürsünüz.
lxml
Lxml, ElementTree’nin işlevselliğini genişleten ve XML belgelerinde gezinmek için bir sorgu dili olan XPath desteği ekleyen harici bir kütüphanedir. Bu örnekte lxml.etree kullanarak bir RSS akışını ayrıştıracak ve gönderi başlıklarını çıkaracağız.
RSS akışını requests.get() ile, önceki örnekte olduğu gibi alarak başlarız. Yanıt içeriği etree.fromstring() yöntemine aktarılır; bu yöntem XML’i ayrıştırır ve kök öğeyi döndürür. lxml ile öğeleri bulmak için XPath ifadelerini kullanabiliriz; çünkü bunlar gezinmeyi standart ElementTree yöntemlerinden daha hızlı ve esnek hâle getirir.
import requests
from lxml import etree
# URL of the RSS feed
FEED_URL = "https://dataimpulse.com/tutorials-category/web-scraping-seo/feed/"
# Download the XML data
response = requests.get(FEED_URL)
xml_data = response.content
# Parse XML
root = etree.fromstring(xml_data)
items = root.xpath("//channel/item")
# Show list of titles with numbers
print("Available blog posts:\n")
for item in items:
title = item.findtext("title")
print(title)
Son olarak, <item> öğeleri üzerinde döngü kurar, her gönderinin başlığını findtext(“title”) kullanarak çıkarır ve yazdırırız.
Minidom
Bu örnekte Minimal DOM Uygulaması kısaltması olan Minidom’u kullanıyoruz. Python’ın standart kütüphanesinin bir parçasıdır ve XML belgesinin tamamını Belge Nesne Modeli (DOM) olarak belleğe yükleyerek çalışır.
Şunu çağırırız: minidom.parseString() ile XML’i ayrıştırır ve bir DOM nesnesi oluştururuz (doc). Bilinen DOM yöntemleri arasında kullanacağımız iki yöntem vardır. İlki getElementsByTagName(“tag”,) olup belirtilen etiket adına sahip tüm öğeleri bulur. Diğeri ise .firstChild.nodeValue ve bu yöntem bir düğümün metin içeriğini alır.
Son olarak toprettyxml(). Bu yöntem, ilk item öğesini biçimlendirilmiş XML düzeninde yazdırmak için kullanılır.
Minidom kullanarak bir RSS akışından verileri şu şekilde ayrıştırabilirsiniz:
import requests
from xml.dom import minidom
# URL of the RSS feed
FEED_URL = "https://dataimpulse.com/tutorials-category/web-scraping-seo/feed/"
# Download XML data
response = requests.get(FEED_URL)
xml_data = response.content
# Parse XML with minidom
doc = minidom.parseString(xml_data)
# Get all - elements
items = doc.getElementsByTagName("item")
print(f"Total articles found in feed: {len(items)}\n")
# Show titles with links
for i, item in enumerate(items, start=1):
title = item.getElementsByTagName("title")[0].firstChild.nodeValue
link = item.getElementsByTagName("link")[0].firstChild.nodeValue
print(f"{i}. {title}")
print(f" Link: {link}\n")
# Show raw XML of the first
- (just for demo)
print("First
- as raw XML:\n")
print(items[0].toprettyxml())
SAX
SAX, XML’i öğe öğe sıralı olarak okur. Her XML bölümü için belirli olayları tetikler:
- startElement(name, attrs) : bir etiket başladığında
- characters(content) : etiketler arasındaki metin okunduğunda
- endElement(name) : bir etiket sona erdiğinde
Kodu dosyaya kaydedin ve çalıştırın:
import requests
import xml.sax
# Custom handler for SAX parsing
class RSSHandler(xml.sax.ContentHandler):
def __init__(self):
super().__init__()
self.current_tag = ""
self.in_item = False
self.title = ""
self.link = ""
self.counter = 0
def startElement(self, name, attrs):
if name == "item":
self.in_item = True
self.title = ""
self.link = ""
self.current_tag = name
def characters(self, content):
if self.in_item:
if self.current_tag == "title":
self.title += content
elif self.current_tag == "link":
self.link += content
def endElement(self, name):
if name == "item":
self.counter += 1
print(f"{self.counter}. {self.title.strip()}")
print(f" Link: {self.link.strip()}\n")
self.in_item = False
self.current_tag = ""
# Download the XML feed
FEED_URL = "https://dataimpulse.com/tutorials-category/web-scraping-seo/feed/"
response = requests.get(FEED_URL)
xml_data = response.content
# Parse XML with SAX
print("Parsing RSS feed with SAX...\n")
handler = RSSHandler()
xml.sax.parseString(xml_data, handler)
print(f"Total items parsed: {handler.counter}")
Bu yöntemin avantajı, belgenin tamamını depolamadığı için bellek açısından verimli olmasıdır.
Untangle
Bu yöntem, XML’i işlemenin daha basit bir yolu olarak kabul edilir. Untangle kütüphanesi XML belgelerini Python nesnelerine dönüştürür. Bu, öğelerde elle gezinmeye veya olay yönetimine gerek olmadığı anlamına gelir.
XML’i untangle.parse(), ile ayrıştırdığınızda XML dosyasını otomatik olarak okur, her XML etiketini bir Python nesnesine dönüştürür ve etiket verilerini .cdata özniteliklerinde saklar (metin içeriğiyse). Düğümlerle veya olaylarla çalışmak yerine XML yapısında normal bir Python nesnesindeymiş gibi gezinebilirsiniz.
Kod aşağıdadır:
import requests
import untangle
from io import BytesIO
# RSS feed from DataImpulse
FEED_URL = "https://dataimpulse.com/tutorials-category/web-scraping-seo/feed/"
# Download XML
resp = requests.get(FEED_URL)
resp.raise_for_status()
xml_bytes = resp.content
# Parse XML with untangle (use BytesIO for bytes input)
doc = untangle.parse(BytesIO(xml_bytes))
# Get all - elements
items = doc.rss.channel.item
print("Articles from DataImpulse RSS:\n")
# Print articles
for i, it in enumerate(items, start=1):
title = it.title.cdata if hasattr(it, "title") else ""
link = it.link.cdata if hasattr(it, "link") else ""
desc = it.description.cdata if hasattr(it, "description") else ""
print(f"{i}. {title}")
print(f" Link: {link}")
if desc:
print(f" Description: {desc}")
print()
Birkaç ek öneri
- Ayrıştırma sırasında hataları denetleyin
Akışlar bazen kullanılamayabilir veya beklenmeyen etiketler içerebilir. Bu tür durumlarda XML’i indirirken ya da ayrıştırırken try/except kullanın.
- .content XML indirmeleri için tercih edin
.content özniteliği ham bayt verisini döndürür ve .text öznitelik neden olabilir.
- Öğelerin mevcut olduğunu doğrulayın
Her XML dosyası aynı yapıya sahip değildir. Etiketlere erişmeden önce if item.find(‘title’) is not None gibi koşullar kullanın.
- Büyük dosyalarda kaynak kullanımına dikkat edin
Çok büyük XML belgelerinde, her şeyi belleğe yüklemeden verileri sıralı olarak okuyan SAX’i kullanın.
Harici sitelerden XML almak sorunlu olabilir. Proxy’ler, farklı konumlarda sorunsuz erişim sağlamaya ve gizliliği korumaya yardımcı olur.
Öne çıkan noktalar
- XML ayrıştırma, XML dosyalarını okuyup verileri yapılandırılmış ve kullanılabilir bir şekilde çıkarma sürecidir.
- ElementTree, XML öğelerinde gezinmek ve onları çıkarmak için ağaç tabanlı bir yaklaşım sunar.
- lxml, daha hızlı XML ayrıştırma için XPath sorgularını destekleyen bir kütüphanedir.
- Minidom, XML’in tamamını DOM ağacı olarak yükler; düğümlere ve metne yapılandırılmış bir nesne gibi erişmenizi sağlar.
- SAX, XML’i her şeyi bellekte tutmadan adım adım işlediği için büyük XML dosyaları için idealdir.
- Untangle, etiketlere ve içeriklerine kolayca erişmek için XML’i Python nesnelerine dönüştürür.
İlgili makaleler
Proxy’leri Python requests ile entegre etme
Python ve proxy’lerle eBay’den veri kazıma
Java’da DataImpulse proxy’lerini yapılandırma
Python ile Amazon ürün verilerini kazıma
Python ile özel bir proxy döngüleyici oluşturma
Python ve Selenium kullanarak güvenlik kontrollerini yönetme
