DOM

1 minute read

1. BeautifulSoup

  • HTML, XML 파일에서 데이터를 가져올 수 있는 파이썬 라이브러리
  • BeautifulSoup을 이용해 DOM 객체로 변환할 수 있음
!pip install beautifulsoup4

from bs4 import BeautifulSoup

2. Parser

  • html parser: 내장되어 있어 별다른 패키지의 도움을 받을 필요가 없음
  • lxml parser: 속도가 빠르다는 장점이 있고 아나콘다를 설치하면 포함되어 있음

3. Dom 객체 만들고 Parsing하기

html = '''
<html>
    <head>
        <title>예제</title>
    </head>
    <body>
        <div>
            <p>
                <a href='/page' class='d' id=adf>페이지이동1</a>
                <a>페이지이동2</a>
            
        </div>
        </p>
        <footer>
            <a class='d'>페이지이동3</a>
        </footer>
    </body>
</html>
'''
dom = BeautifulSoup(html, 'html.parser')

dom.text 
# 내용만 보기
# '\n\n\n예제\n\n\n\n\n페이지 이동\n\n\n\n\n'

4. 탐색

다음 예시와 같이 다양한 방법으로 원하는 태그, 원하는 어트리뷰트, 텍스트에 접근할 수 있다.

dom.html
dom.html.head.title
dom.html.head.title.text # 텍스트 보기
dom.p
dom.body
list(dom.body.children) # 자식요소 리스트로 보기
dom.a.attrs # 속성을 key value 상으로 출력
dom.a['href']
dom.find('a')
dom.find_all('a')[-1].text # 텍스트 보기
dom.find_all({'p', 'a'})
dom.find_all('a', {'id':'adf'}) # 어트리뷰트 검색
dom.find_all(text='페이지이동1') # 텍스트 검색
dom.find_all('a', limit=1) # 개수 제한

node = dom.footer.a

type(node) # bs4.element.Tag

node.find_parent().name # 부모의 이름 찾기

for _ in dom.div.find_all(recursive=False): # 자기 출력 안하기
    print(_.name)
# p

for _ in node.find_parents(limit=2):
    print(_.name)
# footer
# body

node.find_parent().find_parent().find().find('a').find_next_sibling() # <a>페이지이동2</a>
  • find (name, attrs, recursive, string, **kwargs)
    • 하나만 찾기
  • find_all (name, attrs, recursive, string, limit, **kwargs)
    • 모든 자식에 대해 iterate 가능
    • Recursive=False을 지정하면 direct children만 고려한다.
  • find_parent()
    • 해당 요소의 부모 찾기
  • find_parents()
    • 해당 요소의 모든 부모에 대해 iterate 가능
  • find_next_sibling(s), find_previous_sibling(s)
    • 같은 레벨에서 탐색

5. prettify()

html = '''
<html>
    <head>
        <title>예제</title>
    </head>
    <body>
        <div>
            <p>
                <a href='/page' class='d' id=adf>페이지이동1</a>
                <a>페이지 이동2</a>
            
        </div>
        </p>
    </body>
</html>
'''
dom = BeautifulSoup(html, 'lxml')
print(dom.prettify()) # 태그 순서에 맞게 수정해줌

6. CSS Selector

  • tag1 tag2: 자손
    • find_all(recursive=True)와 같음
  • tag1 > tag2: 자식
    • find_all(recursive=False)와 같음
  • tag1 + tag2: 형제 (다음노드)
    • find_next_sibling과 같음
resp = download('http://pythonscraping.com/pages/page3.html')
dom = BeautifulSoup(resp.text, 'lxml')
# id가 footer인 태그의 텍스트 가져오기
dom.select_one('#footer').text.strip()

# id가 wrapper인 태그의 자식 요소 이름 가져오기
{_.name for _ in dom.select('#wrapper > *')}

# h1 태그 -> 다음노드 div -> 이전노드 h1
dom.select_one('h1 + div').find_previous_sibling().name

# body 밑에 div 밑에 있는 h1 옆에 있는 div 찾기
dom.select_one('body > div > h1 + div').name

# 클래스가 gift인 태그의 자식요소 td 중 3번째 텍스트 가져오기
[_.text.strip() for _ in dom.select('.gift > td:nth-of-type(3)')]

# 클래스가 gift인 태그 밑 td 밑 img의 src 가져오기
[_['src'].strip() for _ in dom.select('.gift > td > img')]

Leave a comment