우리는 웹을 통해 필요한 정보를 얻습니다. 목적한 데이터를 자동화 프로그램을 통해 수집, 가공하는 행위를 "스크래핑" 혹은 "크롤링" 이라고 합니다.
(웹 크롤링은 자동화된 시스템에 의해 최신의 정보를 수집, 가공하는 조직화된 시스템으로 해당 의미에서 스크래핑과는 약간의 의미 차이가 있습니다.)
python은 웹 데이터 수집, 가공을 위해 많은 외부라이브러리를 제공합니다.
HTTP library 인 Reqeusts 와 HTML, XML Parsing library 인 Beautiful Soup4 (BS4) 를 사용해서 간단한 웹 스크래핑 기술을 살펴보겠습니다.
참조
https://requests.readthedocs.io/en/master/#
https://www.crummy.com/software/BeautifulSoup/bs4/doc/
1. Library install
- Anaconda( https://www.anaconda.com/distribution/#download-section ) 가 설치 되어있거나 pip 패키지를 사용할 수 있는 환경
- Requests & BeautifulSoup4 설치
pip install beautifulsoup4
pip install requests
2. Python 공식 홈페이지 스크래핑
2.1. Python 홈페이지 url HTTP 요청
import requests
from bs4 import BeautifulSoup
r = requests.get('https://www.python.org/');
r.encoding
Out[3]: 'utf-8'
r.status_code # HTTP 응답코드
Out[4]: 200
2.2. BeautifulSoup 사용하여 text 를 html 로 파싱
soup = BeautifulSoup(r.text, 'html.parser')
print(soup.prettify())
Out [1]: .....생략
</script>
<!--[if lte IE 7]>
<script type="text/javascript" src="/static/js/plugins/IE8-min.798605d5f7a2.js" charset="utf-8"></script>
<![endif]-->
<!--[if lte IE 8]>
<script type="text/javascript" src="/static/js/plugins/getComputedStyle-min.c3860be1d290.js" charset="utf-8"></script>
<![endif]-->
</body>
</html>
2.3. BeautifulSoup 셀렉터 기능을 사용하여 목적데이터 가져오기
- BeautilfulSoup 셀렉터
soup.title
Out[1]: <title>Welcome to Python.org</title>
soup.title.name
Out[2]: 'title'
soup.title.string
Out[3]: 'Welcome to Python.org'
soup.p
Out[4]: <p><strong>Notice:</strong> While Javascript is not essential for this website, your interaction with the content will be limited. Please turn Javascript on for the full experience. </p>
- A 태그 모두 조회
soup.find_all('a')
Out[1]:
[<a href="#content" title="Skip to content">Skip to content</a>,
<a aria-hidden="true" class="jump-link" href="#python-network" id="close-python-network">
<span aria-hidden="true" class="icon-arrow-down"><span>▼</span></span> Close
</a>,
<a class="current_item selectedcurrent_branch selected" href="/" title="The Python Programming Language">Python</a>,
<a href="/psf-landing/" title="The Python Software Foundation">PSF</a>
... 생략
len(soup.find_all('a')) # 모든 A 태그 수
Out[2]: 206
- A 태그의 href 속성값이 정규식 http[s]? 와 매칭되는 요소 찾기
import re
result = [x for x in list_a if re.search('http[s]?', x['href'])]
result
Out[1]:
[<a href="https://docs.python.org" title="Python Documentation">Docs</a>,
<a href="https://pypi.python.org/" title="Python Package Index">PyPI</a>,
<a href="https://www.facebook.com/pythonlang?fref=ts"><span aria-hidden="true" class="icon-facebook"></span>Facebook</a>,
<a href="https://twitter.com/ThePSF"><span aria-hidden="true" class="icon-twitter"></span>Twitter</a>,
<a href="http://brochure.getpython.info/" title="">Python Brochure</a>,
<a href="https://docs.python.org/3/license.html" title="">License</a>,
... 생략 ]
- 본 예제에서는 Upcoming Event HTML 요소에 접근합니다.
- 크롬의 개발자도구( F12 ) 를 사용하여 HTML Element 요소에 접근합니다. 목적한 데이터를 찾을때 용이한 방법으로
목적데이터의 HTML / CSS 구조를 파악합니다. 해당 구조를 알아야 BeautifulSoup 셀렉터를 어떻게 사용할 것인지
판단 할 수 있습니다.
- 목적데이터( Upcoming Events ) 에 접근하기 위해 상위 엘리먼트인 "main-content"를 class로 갖는 section 태그 셀렉트
main_container = soup.find('section', attrs={"class":"main-content"})
Out[25]:
<section class="main-content" role="main">
<div class="row">
(중략...)
<div class="medium-widget event-widget last">
<div class="shrubbery">
<h2 class="widget-title"><span aria-hidden="true" class="icon-calendar"></span>Upcoming Events</h2>
<p class="give-me-more"><a href="/events/calendars/" title="More Events">More</a></p>
<ul class="menu">
<li>
<time datetime="2020-02-18T00:00:00+00:00"><span class="say-no-more">2020-</span>02-18</time>
<a href="/events/python-events/880/">PyCon Namibia 2020</a></li>
<li>
<time datetime="2020-02-20T00:00:00+00:00"><span class="say-no-more">2020-</span>02-20</time>
<a href="/events/python-events/946/">Open Source Festival</a></li>
<li>
<time datetime="2020-02-21T00:00:00+00:00"><span class="say-no-more">2020-</span>02-21</time>
<a href="/events/python-events/890/">PyCon Belarus 2020</a></li>
<li>
<time datetime="2020-02-25T23:00:00+00:00"><span class="say-no-more">2020-</span>02-25</time>
<a href="/events/python-user-group/944/">Visual Diagnostics for Machine Learning with Python</a></li>
<li>
<time datetime="2020-02-29T06:00:00+00:00"><span class="say-no-more">2020-</span>02-29</time>
<a href="/events/python-user-group/950/">Python Mauritius User Group Meetup</a></li>
</ul>
(중략...)
</p>
</div>
</section>
- 위에서 가져온 main_container의 내용을 살펴보면 목적데이터 Upcoming Events가 존재하는 것을 확인할 수 있습니다. find 태그로 목적데이터에 접근하여 상위(parent) 태그로 위치한 후 findNext 로 ul 엘리먼트 요소를 가져옵니다.
target_data = main_container.find(text="Upcoming Events").parent.findNext('ul')
print(target_data)
Out[34]:
<ul class="menu">
<li>
<time datetime="2020-02-18T00:00:00+00:00"><span class="say-no-more">2020-</span>02-18</time>
<a href="/events/python-events/880/">PyCon Namibia 2020</a></li>
<li>
<time datetime="2020-02-20T00:00:00+00:00"><span class="say-no-more">2020-</span>02-20</time>
<a href="/events/python-events/946/">Open Source Festival</a></li>
<li>
<time datetime="2020-02-21T00:00:00+00:00"><span class="say-no-more">2020-</span>02-21</time>
<a href="/events/python-events/890/">PyCon Belarus 2020</a></li>
<li>
<time datetime="2020-02-25T23:00:00+00:00"><span class="say-no-more">2020-</span>02-25</time>
<a href="/events/python-user-group/944/">Visual Diagnostics for Machine Learning with Python</a></li>
<li>
<time datetime="2020-02-29T06:00:00+00:00"><span class="say-no-more">2020-</span>02-29</time>
<a href="/events/python-user-group/950/">Python Mauritius User Group Meetup</a></li>
</ul>
- 위에 보이는것 처럼 BeautifulSoup의 강력한 Selector 기능으로 HTML내의 목적한 데이터를 쉽게 접근하여 가져왔습니다.
- 목적데이터를 dictionary 데이터 구조에 적재합니다.
upcoming_events_dict = {}
for li in target_data.findAll('li'):
upcoming_events_dict[li.time.text] = li.a.text
print(upcoming_events_dict)
Out[1]:
{'2020-02-18': 'PyCon Namibia 2020',
'2020-02-20': 'Open Source Festival',
'2020-02-21': 'PyCon Belarus 2020',
'2020-02-25': 'Visual Diagnostics for Machine Learning with Python',
'2020-02-29': 'Python Mauritius User Group Meetup'}
3. 마치며
웹스크래핑을 위한 Python의 강력한 외부 라이브러리 bs4 ( BeautifulSoup )와 Requests 를 사용하여 간단한 스크래핑을 해보았습니다. bs4는 목적데이터를 가져오기 위해 많은 함수를 제공하고 있습니다. 이를 활용하여 개발자는 손쉽게 데이터를 가져올 수 있고 가공할 수 있습니다.
HTML, XML Parser중 bs4 외에 lxml 이라는 외부 라이브러리도 많이 사용되며 기회가 된다면 다음 블로그에서 본 예제처럼 간단히 살펴보는 기회를 갖도록 하겠습니다.
감사합니다.
'python' 카테고리의 다른 글
Python - XML 파싱 오류 해결 ( xml.etree.ElementTree.ParseError ) (1) | 2020.12.07 |
---|---|
python - 타입 비교, 이런방식도 있었어? (0) | 2020.03.24 |
python - 디렉토리에 파일존재 유무 체크 ( open, os.path, pathlib ) (0) | 2020.03.07 |
python - lambda 활용법과 단점 (0) | 2020.02.14 |
python - 정규 표현식 사용법과 예제( validate IP, email, phone ) (0) | 2019.12.24 |