-
데이터 사이언스: 파이썬 Beautiful Soup 모듈 이용해서 파싱(Parsing)하기!데이터 사이언스 2020. 8. 4. 03:54
파싱(Parsing)이란?
파싱은 문자의 구조를 분석해서 원하는 정보를 얻어내는 것입니다.
쉽게 말해서 웹 파싱이라하면 웹에서 필요한 정보를 찾아 가져오는 것을 의미하죠.
예를 들어, 네이버의 실시간 검색어에 대한 정보가 필요하다면 이를 파싱해서 가져올 수도 있습니다.
스크래핑과 크롤링 같은것? 같습니다. 정확하게는 잘모르겠네요ㅋㅋㅋ파이썬에서 파싱을 하기 위한 대략적인 절차는 다음과 같습니다.
먼저 내가 파싱하고자 하는 웹사이트의 주소에 요청(request)을 보냅니다.
응답이 내가 정해놓은 변수에 저장되었다면
html 코드를 Beautiful soup타입을 바꾸어 준 후,
select() 메소드를 이용해서 원하는 태그를 가져옵니다.
(웹사이트 아무곳에서 마우스 우측 버튼을 누르신 후 검사(N)를 누르면 그 웹사이트의 html을 확인할 수 있습니다)
말로만 말고 직접 신세계몰 웹 사이트를 이용해서 연습 한번 해봅시다.
사이트에 들어가시면 좌측의 카테고리가 있습니다.
여성언더웨어/언더웨어부터 문구/취미/반려동물까지 있는데 이 카테고리 목록을 가져오겠습니다.
request로 신세계 몰에 요청을 보냅니다.
응답이 오면 soup에 Beautifulsoup 모듈을 이용해 다음과 같이 page을 읽어줍니다.
from bs4 import BeautifulSoup # BeautifulSoup를 사용하기 위함 import requests # 웹에 요청을 보내기 위함 page = requests.get("http://shinsegaemall.ssg.com/main.ssg?ckwhere=s_nabr&EKAMS=naver.32.5169.20079.2036871.601889975&trackingDays=1") # 내가 원하는 웹에 요청을 보낸다. soup = BeautifulSoup(page.text, "html.parser") # html.parser를 이용해서 BeautifulSoup 형태로 바꾸어줍니다. soup
soup에 어떤 값이 들어갔는지 잠깐 확인하고 갑시다.
soup는 다음과 같이 <!DOCTYPE html> 파일 형태로 만들어집니다.
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="utf-8"/> <meta content="IE=edge" http-equiv="X-UA-Compatible"/> <title class="notranslate">신세계몰</title> <link href="//ui.ssgcdn.com/ui/common/img/sm.ico" rel="shortcut icon" type="image/x-icon"/> <link href="http://ui.ssgcdn.com/ui/common/img/sns/sm.png" rel="image_src"> <meta content="부러움을 사다, 신세계몰" name="title"/> <meta content="패션에서 생활까지, 명품 공식스토어부터 디자이너 상품까지 다양한 브랜드로 특별한 쇼핑을 하다. GUCCI, BURBERRY, YOOX, Scandinavian Design Center, DISNEY, MASSIMO DUTTI 외 공식스토어 입점" name="description"/> <meta content="riDJ-IX46HanskLx25pj6-y8ANf2qTgZNfv_UJvkHq8" name="google-site-verification"/> <link href="//ui.ssgcdn.com/ui/ssg/css/common/common_layout.css?v=20200728" rel="stylesheet" type="text/css"/> <link href="//ui.ssgcdn.com/ui/ssg/css/common/common_unit.css?v=20200728" rel="stylesheet" type="text/css"/> <link href="//ui.ssgcdn.com/ui/sm/css/base_v1.css?v=20200728" rel="stylesheet" type="text/css"/> <link href="//ui.ssgcdn.com/ui/sm/css/main_sm_v2.css?v=20200728" rel="stylesheet" type="text/css"/> <link href="//ui.ssgcdn.com/ui/sm/css/quick_view.css" rel="stylesheet" type="text/css"/> <link href="//ui.ssgcdn.com/ui/sm/css/global_sm.css?v=20200728" rel="stylesheet" type="text/css"/><script src="//ui.ssgcdn.com/ui/ssg/js/lib/jquery-1.9.1.min.js" type="text/javascript"></script> <script src="//ui.ssgcdn.com/ui/ssg/js/lib/jquery.cookie.min.js" type="text/javascript"></script>
(너무 길어서 짤랐습니다)
제가 필요한 카테고리 목록에 대한 정보는
class = ".smctg_top_mn" 안
a 태그 안
span 태그 안에 있네요
soup.select() 메소드는 내가 원하는 부분을 파싱할 수 있게 합니다.
soup.select(".smctg_top_mn > a > span") 라고 하면 제가 원하는 부분을 찾을 수 있겠네요
category = soup.select(".smctg_top_mn > a > span") category
[<span class="smctg_lnk_txt notranslate">여성패션/언더웨어</span>, <span class="smctg_lnk_txt notranslate">남성캐쥬얼/유니섹스</span>, <span class="smctg_lnk_txt notranslate">패션잡화/패션슈즈</span>, <span class="smctg_lnk_txt notranslate">명품/직구/시계/쥬얼리</span>, <span class="smctg_lnk_txt notranslate">뷰티X 먼데이문</span>, <span class="smctg_lnk_txt notranslate">유아동용품/패션</span>, <span class="smctg_lnk_txt notranslate">스포츠/레저/헬스/골프</span>, <span class="smctg_lnk_txt notranslate">가구/침구/인테리어</span>, <span class="smctg_lnk_txt notranslate">주방/생활/건강</span>, <span class="smctg_lnk_txt notranslate">식품</span>, <span class="smctg_lnk_txt notranslate">디지털/컴퓨터/자동차용품</span>, <span class="smctg_lnk_txt notranslate">영상/주방/생활가전</span>, <span class="smctg_lnk_txt notranslate">여행/상품권/서비스</span>]
파싱이 잘 되었습니다. 하지만 모두 text형태가 아니라 span이라는 태그가 씌어져 있네요
이렇게 파싱한 값들은 처음엔 모두 태그가 씌어진 형태입니다.
다음과 같이 text형태로 하나하나 바꾸어 줍시다.
for i in range(len(category)): category[i] = category[i].text category
['여성패션/언더웨어', '남성캐쥬얼/유니섹스', '패션잡화/패션슈즈', '명품/직구/시계/쥬얼리', '뷰티X 먼데이문', '유아동용품/패션', '스포츠/레저/헬스/골프', '가구/침구/인테리어', '주방/생활/건강', '식품', '디지털/컴퓨터/자동차용품', '영상/주방/생활가전', '여행/상품권/서비스']
이렇게 카테고리 목록을 모아 봤습니다.
2. 프로틴 페이지 모두 받아오기
이번에는 신세계몰에 "프로틴"을 검색한 뒤
프로틴 검색결과가 나오지 않는 페이지까지 모든 페이지를 파싱해 보겠습니다.
"검색어와 일치하는 상품이 없습니다." 란이 나올때까지 파싱할겁니다.
"검색어와 일치하는 상품이 없습니다"의 html을 확인해보니
class = "csrch_tip" 일때 위 문구가 뜹니다.
그렇다면 "csrch_tip" 전 페이지까지만 받아오면 되겠습니다.
from bs4 import BeautifulSoup import requests page = requests.get("http://shinsegaemall.ssg.com/search.ssg?target=all&query=%ED%94%84%EB%A1%9C%ED%8B%B4&page=1") soup = BeautifulSoup(page.text, "html.parser") ssg_page = [] # soup 페이지를 담을 리스트 i = 1 # 페이지 수입니다. while True: if len(soup.select(".csrch_tip")) != 0: break # .csrch_tip이 나오기 전까지 페이지를 받아오겠다는 의미입니다. page = requests.get("http://shinsegaemall.ssg.com/search.ssg?target=all&query=%ED%94%84%EB%A1%9C%ED%8B%B4&page={}".format(i)) soup = BeautifulSoup(page.text,"html.parser") ssg_page.append(soup) # ssg_page에 soup담기 i += 1 # 페이지수 하나 더하기 print(ssg_page[0])
페이지가 잘 받아졌는지 첫번째 페이지만 확인해보면
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="utf-8"/> <meta content="IE=edge" http-equiv="X-UA-Compatible"/> <title class="notranslate">검색결과 >프로틴, 신세계몰</title> <link href="//ui.ssgcdn.com/ui/common/img/sm.ico" rel="shortcut icon" type="image/x-icon"/> <link href="http://ui.ssgcdn.com/ui/common/img/sns/sm.png" rel="image_src"> <meta content="프로틴-신세계몰" name="title"/> <meta content="프로틴도 한번에 쓱~ 신세계몰 검색결과 입니다.단백질파우더,프로틴바,헬스보충제,다이어트보조제,닭가슴살" name="description"/> <meta content="riDJ-IX46HanskLx25pj6-y8ANf2qTgZNfv_UJvkHq8" name="google-site-verification"/> <link href="//ui.ssgcdn.com/ui/ssg/css/common/common_layout.css?v=20200728" rel="stylesheet" type="text/css"/> <link href="//ui.ssgcdn.com/ui/sm/css/base_v1.css?v=20200728" rel="stylesheet" type="text/css"/> <link href="//ui.ssgcdn.com/ui/sm/css/global_sm.css?v=20200728" rel="stylesheet" type="text/css"/> <link href="//ui.ssgcdn.com/ui/ssg/css/common/common_unit.css?v=20200728" rel="stylesheet" type="text/css"/> <link href="//ui.ssgcdn.com/ui/sm/css/quick_view.css" rel="stylesheet" type="text/css"> <script src="//ui.ssgcdn.com/ui/ssg/js/lib/jquery-1.9.1.min.js" type="text/javascript"></script> <script src="//ui.ssgcdn.com/ui/ssg/js/lib/jquery.cookie.min.js" type="text/javascript"></script> <script type="text/javascript"> var settings = { localDomain : location.hostname, domain : { isHttpFlag:'true' == 'true' ? true : false,
(마찬가지로 너무 길어서 짤랐습니다)
잘 받아졌군요!
3. 프로틴 상품 정보 받아와서 데이터프레임으로 만들기
본격적인 데이터 만들기 입니다.
2번 연습 문제에서 좀 더 나아가서 페이지를 모두 받아온 후, 그 페이지 안에 있는 모든 상품 정보를 파싱할겁니다.
각 상품의 브랜드와 그에 대한 설명 그리고 할인된 가격을 받아오겠습니다.
상품명은 ".title a .tx_ko" 안에 있네요
이런식으로 브랜드와 가격도 찾아줍시다.
from bs4 import BeautifulSoup import pandas as pd import requests page = requests.get("http://shinsegaemall.ssg.com/search.ssg?target=all&query=%ED%94%84%EB%A1%9C%ED%8B%B4&page=1") soup = BeautifulSoup(page.text, "html.parser") i = 1 # 페이지 번호입니다. product_list = [] # 상품들의 정보를 담을 리스트 while True: if len(soup.select(".csrch_tip")) != 0: break # 모든 페이지를 받아오겠다. page = requests.get("http://shinsegaemall.ssg.com/search.ssg?target=all&query=%ED%94%84%EB%A1%9C%ED%8B%B4&page={}".format(i)) soup = BeautifulSoup(page.text,"html.parser") brand = soup.select(".brd > .tx_ko") # 브랜드를 받아오겠다. name = soup.select(".title a .tx_ko") # 상품명을 받아오겠다. price = soup.select(".opt_price .ssg_price") # 상품가격을 받아오겠다. for j in range(len(brand)): product = [] # 상품 정보 product.append(name[j].text.strip()) # 상품 이름 넣기 product.append(brand[j].text) # 상품 브랜드 넣기 product.append(price[j].text) # 상품 가격 넣기 product_list.append(product) # 상품 리스트에 상품 넣기 i += 1 # 페이지 수 하나 더하기 # 내가 만든데이터를 판다스 데이터프레임으로 이쁘게 만들어보자 df = pd.DataFrame(product_list, columns = ["Product name", "Brand", "Price"]) df.set_index("Product name")
이렇게 모든 페이지에 있는 모든 프로틴 상품 목록들을 받아왔습니다.
반응형'데이터 사이언스' 카테고리의 다른 글