[Python.Web] BeautifulSoup과 wget 으로 웹크롤링, 데이터 스크레이핑

2020. 11. 23. 05:00Python과 머신러닝/웹 데이터 추출

이전 포스트

 

[Python.Web] 정규표현식을 이용한 웹 데이터 파싱 - urllib, regular expression

웹사이트에서 원하는 형태의 데이터를 긁어오는 방법을 알아보자. 0. 요약 1. 원하는 URL을 정한다. 2. URL로부터 모든 text를 string으로 읽어온다. 3. 내가 찾고자 하는 string을 regular expression 형태로

coding-grandpa.tistory.com

 

[Python.Web] wget으로 웹 데이터 다운로드 및 파싱 - wget.download

요약 한 웹사이트에서 여러 가지의 파일을 다운로드하고 싶을 때에, wget을 사용하여 한번에 다운 받는 프로그램을 짤 수 있다 이전에 정리한 내용에 이어서, 정규식을 사용하여 원하는 파일을

coding-grandpa.tistory.com

 

[Python.Web] 실시간 금융 데이터 파싱하기 추출

요약 URL로부터 정보를 뽑아오는 3번째 예제이다 (앞의 예제를 못 봤다면 참고해야 이해가 될 것이다) Python으로 웹사이트에서 데이터 추출하기 (urllib, regular expression) 웹사이트에서 원하는 형태의

coding-grandpa.tistory.com

 

[Python.Web] BeautifulSoup으로 하는 웹크롤링, 데이터 스크레이핑

요약 XML이란 eXtensible Markup Language의 약자로 데이터의 구조와 의미를 설명하기 위해 Tag(Markup)를 사용하는 언어이다. HTML과 비슷하게 데이터가 정형화되어 있어 분석이 편리하고, 이를 더욱 쉽게 Pa

coding-grandpa.tistory.com

 

요약

  • 지난 내용은 다운로드하여놓은 xml파일을 분석했다면, 이번엔 웹에서 다운로드하는 단계까지 자동화한다

 

 

BeautifulSoup으로 하는 웹크롤링, 데이터 스크레이핑

요약 XML이란 eXtensible Markup Language의 약자로 데이터의 구조와 의미를 설명하기 위해 Tag(Markup)를 사용하는 언어이다. HTML과 비슷하게 데이터가 정형화되어 있어 분석이 편리하고, 이를 더욱 쉽게 Pa

coding-grandpa.tistory.com

 

  • wget을 사용하여 개발자가 매번 다운로드하는 수고도 덜도록 작성해보자.
  • 늘 그렇듯 정답부터 보고 시작하자.
import wget
import os
from bs4 import BeautifulSoup

url = "https://www.w3schools.com/xml/simple.xml"

filename = url.split("/")[-1]

if not os.path.exists(filename):
    wget.download(url)

with open(filename, "r", encoding="utf8") as menu:
    menu_xml = menu.read()

soup = BeautifulSoup(menu_xml, "lxml")

breakfast_menu_tag = soup.find("breakfast_menu") # xml 중 breakfast_menu 만 추출

food_tag = breakfast_menu_tag.find("food") # breakfast menu 중 food tag 추출
food_name = food_tag.find("name").get_text() # food tag 내의 name 정보만 추출 (Tag 제외)
food_price = food_tag.find("price").get_text() # food tag 내의 price 정보만 추출 (Tag 제외)
food_desc = food_tag.find("description").get_text() # food tag 내의 desc 정보만 추출 (Tag 제외)
food_calories = food_tag.find("calories").get_text() # food tag 내의 calories 정보만 추출 (Tag 제외)

print(food_name, food_price, food_desc, food_calories) # food tag 정보가 잘 추출되었는지 확인

 

1. 파일이 있는지 확인하여, 없을 경우에만 다운로드하기

  • 파일이 있을 때 또 다운로드 하지 않도록 검증하는 간단한 코드를 os.path.exists를 통해서 작성해주자.
  • 파일을 다운로드한 뒤에는 xml을 읽어 들이면, 매번 손으로 다운로드하지 않고 url만 입력해주어 자동화할 수 있다
import wget
import os
from bs4 import BeautifulSoup

url = "https://www.w3schools.com/xml/simple.xml"

filename = url.split("/")[-1]

if not os.path.exists(filename): # filename의 파일이 현 working directory에 존재하지 않는다면
    wget.download(url) # 다운받는다

with open(filename, "r", encoding="utf8") as menu: # 존재하거나 새로 다운받은 파일을 메뉴로 읽어서
    menu_xml = menu.read() # 메뉴의 내용을 menu_xml로 읽어들인다

 

2. menu_xml로 읽은 string을 BeautifulSoup으로 Parsing 한다

  • 단순 read를 하여서 string으로 전달받은 내용을 lxml로 parsing 하고
  • soup 객체 내에서 breakfast_menu 등 원하는 tag를 찾을 수 있다
soup = BeautifulSoup(menu_xml, "lxml")

breakfast_menu_tag = soup.find("breakfast_menu") # xml 중 breakfast_menu 만 추출

 

3. Tag를 계속 타고 들어가, 원하는 데이터만 get_text로 추출한다.

  • find : XML 중 원하는 tag 정보만 추출한다.
  • get_text : find의 결괏값 중에서 tag는 제외하고 text만 추출하여 사용한다.
food_tag = breakfast_menu_tag.find("food") # breakfast menu 중 food tag 추출
food_name = food_tag.find("name").get_text() # food tag 내의 name 정보만 추출 (Tag 제외)
food_price = food_tag.find("price").get_text() # food tag 내의 price 정보만 추출 (Tag 제외)
food_desc = food_tag.find("description").get_text() # food tag 내의 desc 정보만 추출 (Tag 제외)
food_calories = food_tag.find("calories").get_text() # food tag 내의 calories 정보만 추출 (Tag 제외)

print(food_name, food_price, food_desc, food_calories) # food tag 정보가 잘 추출되었는지 확인

 

마무리

  • XML을 string으로 읽어서 lxml로 parsing을 하고, find/get_text를 통해서 원하는 tag와 text를 자유롭게 찾을 수 있다면, 웹에 흩뿌려진 데이터를 추출해서 모으는 것이 매우 쉬울 것이다.