구글에 xml 파싱이라고 검색하면 가장 먼저 나오는 결과는 xml.etree.ElementTree라는 파이썬 기본 라이브러리를 이용하는 방식이 나온다. 나쁜 라이브러리는 아니지만 매번 xml.etree.ElementTree라고 치기는 번거로울 뿐더러 사용 방식도 썩 직관적이진 않다. 따라서 필자는 조금 더 사용성이 좋고 다양한 방식으로 활용할 수 있는 BeautifulSoup를 활용하는 것을 권한다. 아래에서는 BeautifulSoup로 파싱하는 방법에 대해 다룬다.
설치는 다음과 같은 명령어를 사용하면 된다. 두 명령어 모두 입력해 주자.
pip install bs4
pip install lxml
w3cschools에서 제공하는 간단한 xml파일을 분석하며 xml파일을 분석하는 방법을 알아보자.
from pathlib import Path
from bs4 import BeautifulSoup
import requests
# requests를 이용해 xml 파일을 불러온다.
xmlstring = requests.get("https://www.w3schools.com/xml/plant_catalog.xml").text
# BeautifulSoup를 이용해 xml파일을 파싱한다.
soup = BeautifulSoup(xmlstring, "xml")
만약 이미 존재하는 xml 파일을 불러올 계획이라면 다음의 코드를 사용해 보자.
from pathlib import Path from bs4 import BeautifulSoup xmlstring = Path(r'somefile.xml').read_text(encoding='utf-8')
이 코드에서는 pathlib나 encoding, raw text등 몇 가지 기술이 들어가지만 주제에서 벗어나는 이야기니 원한다면 직접 찾아보도록 하자.
xml 파일을 BeatifulSoup를 통해 불러오는 데 성공했다. soup
나 soup.prettify()
를 통해 값을 확인할 수 있다.
# 이전 파일에서 이어짐
print(soup)
# 출력값
# <?xml version="1.0" encoding="utf-8"?>
# <CATALOG>
# <PLANT>
# <COMMON>Bloodroot</COMMON>
# <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
# <ZONE>4</ZONE>
# <LIGHT>Mostly Shady</LIGHT>
# <PRICE>$2.44</PRICE>
# <AVAILABILITY>031599</AVAILABILITY>
# </PLANT>
# ...
# <AVAILABILITY>022299</AVAILABILITY>
# </PLANT>
# </CATALOG>
# 출력값을 보기 좋게 만든다.
print(soup.prettify())
# 출력값
# <?xml version="1.0" encoding="utf-8"?>
# <CATALOG>
# <PLANT>
# <COMMON>
# Bloodroot
# </COMMON>
# <BOTANICAL>
# Sanguinaria canadensis
# </BOTANICAL>
# ...
이렇게 불러와진 xml파일은 두 가지 방식으로 사용할 수 있다.
xml 내에 있는 내용을 .
을 계속해서 잇는 방식으로 사용할 수 있다. select
나 select_one
이 더 기능이 많아서 잘 사용하진 않는다.
# 이전 파일에서 이어짐
# 만약 해당하는 동등한 객체가 여러 개 있을 경우 맨 처음 것만 불러와짐.
print(soup.CATALOG.PLANT)
# <PLANT>
# <COMMON>Bloodroot</COMMON>
# <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
# <ZONE>4</ZONE>
# <LIGHT>Mostly Shady</LIGHT>
# <PRICE>$2.44</PRICE>
# <AVAILABILITY>031599</AVAILABILITY>
# </PLANT>
BeautifulSoup에서는 .select()
나 .select_one()
을 사용하면 CSS 선택자를 통해 개체를 선택할 수 있다.
print(soup.select("PLANT"))
# [<PLANT>
# <COMMON>Bloodroot</COMMON>
# <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
# <ZONE>4</ZONE>
# <LIGHT>Mostly Shady</LIGHT>
# <PRICE>$2.44</PRICE>
# <AVAILABILITY>031599</AVAILABILITY>
# </PLANT>,
# <PLANT>
# <COMMON>Columbine</COMMON>
# <BOTANICAL>Aquilegia canadensis</BOTANICAL>
# <ZONE>3</ZONE>
# <LIGHT>Mostly Shady</LIGHT>
# <PRICE>$9.37</PRICE>
# <AVAILABILITY>030699</AVAILABILITY>
# </PLANT>,
# ...
Tag
가 아닌 list
임에 주의하자. for loop에 돌리면 좋다..select_one()
은 .select()[0]
과 동일하다고 보면 된다.