xml을 파싱하는 가장 좋은 방법

ilotoki·2023년 7월 5일
0
post-thumbnail
post-custom-banner

서론

구글에 xml 파싱이라고 검색하면 가장 먼저 나오는 결과는 xml.etree.ElementTree라는 파이썬 기본 라이브러리를 이용하는 방식이 나온다. 나쁜 라이브러리는 아니지만 매번 xml.etree.ElementTree라고 치기는 번거로울 뿐더러 사용 방식도 썩 직관적이진 않다. 따라서 필자는 조금 더 사용성이 좋고 다양한 방식으로 활용할 수 있는 BeautifulSoup를 활용하는 것을 권한다. 아래에서는 BeautifulSoup로 파싱하는 방법에 대해 다룬다.

  • 파싱: 파일을 원하는 데로 사용할 수 있게 분석하는 것.

설치

설치는 다음과 같은 명령어를 사용하면 된다. 두 명령어 모두 입력해 주자.

pip install bs4
pip install lxml
  • 리눅스에서 lxml을 사용하려면 추가적인 패키지를 설치해야 한다.

특징 및 장단점

  • 파이썬에 기본으로 포함되어 있지 않다.
  • CSS 선택자는 있지만 xpath를 사용하기 어렵다(CSS 선택자가 익숙하다면 장점이다.)
  • 추후에 웹 스크래핑을 할 계획이 있거나 이미 해본 적이 있다면 사용 방법이 같아 편리하다.

예시

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를 통해 불러오는 데 성공했다. soupsoup.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 내에 있는 내용을 .을 계속해서 잇는 방식으로 사용할 수 있다. selectselect_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>

.select()나 .select_one()을 이용하는 방식

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]과 동일하다고 보면 된다.
  • case-sensitive하니 주의해야 한다.
post-custom-banner

0개의 댓글