2019. 1. 20. 19:04ㆍUdacity Nanodegree/Natural Language Processing
일단 request라이브러리를 이용해서 udacity홈페이지를 크롤링 해보자. requests라이브러리를 사용하면 웹페이지의 내용을 그대로 가져올 수 있다.
import requests
# Fetch a web page
r = requests.get("https://www.udacity.com/courses/all")
print(r.text)
정규표현식을 쓰는건 어떨까? 일단 HTML태그의 모양을 정의하고 그 모양에 맞는 패턴이 나온다면 공백으로 바꿔주는 방법을 써보자.
import re
# Remove HTML tags using RegEx(Regular expressions)
pattern = re.compile(r'<.&?>') # tags looks like <...>
print(pattern.sub('', r.text))
이 코드의 결과는 아래와 같다.
여기서 우리가 필요한건 HTML을 분리하는것이다. (마치 웹브라우저에서 보이듯이!) 그리고 또 하나, HTML과 관련이 높아보이는 부분은 빼버리는 것이다.
이것이 BeautifulSoup 라이브러리가 필요한 이유이다. BeautifulSoup 라이브러리는 정확하게 이 용도를 위해서 개발된 툴이다! 이제 내가 해야할 것은 그냥 웹페이지에서 나온 텍스트를 모두 Soup객체에 던져주고 get_text 메쏘드를 이용해서 일반 텍스트를 추출한 결과를 받는것이다. 이러한 방법은 nested형태의 태그나 여러줄에 걸친 태그, 그 외에 여러 엄청나게 번거로운 HTML 파싱을 해결해준다! 또한 사소한 HTML오류정도는 너그럽게 넘어가준다. (친절도 하셔라...)
일단 코드를 다시 작성해보자.
from bs4 import BeautifulSoup
# Remove HTML tags using Beautiful Soup Library
soup = BeautifulSoup(r.text, "html5lib")
print(soup.get_text())
좀 나아진게 보인다!! 아직 Javascript 코드나 상당수의 공백이 남아있기는 하다... 뭔가 다른 방법은 또 없을까? 이번엔 HTML이 어떤 구조로 되어있는가 살펴보자.
여기서 '검사(N)'을 누르면 HTML소스코드를 그대로 볼 수 있다.
(크롬기준으로 메뉴 - 도구 더보기 - 개발자 도구 를 사용해서 같은 동작을 할 수 있다.)
제목부분을 따로 살펴보면 상세 HTML태그를 볼 수 있는데, 시연 영상과는 달리 여기서는 보기가 힘들다...이럴때는 개발자도구 왼쪽 위에 있는 아이콘 (아래그림)을 눌러서 살펴보자.
그렇게 제목을 누르면 아래와 같은 꽤 괜찮은 형태의 태그를 볼 수 있다. 일단 써보자.
일단 내가 사용한 태그는 "card__inner card mb-0"이라는 태그이다.
# Find all course summaries
soup.find_all("div", class_="card__inner card mb-0")
일단 이걸로 수정해서 한번 더 결과를 보려고 했는데... 다시 안나온다.
또 다시 구글링해보니 Javascript 코드를 찾으려면 Phantom JS라는것을 설치해야 한다고 한다. 일단 설치해보고 다시 진행해보자... (친절한 가이드: https://programmingsummaries.tistory.com/365)
검색해본 결과 새로운 코드를 써서 해야 하는것 같다. 아래와 같은 코드를 새롭게 짜서 시도해봤다.
import requests
from bs4 import BeautifulSoup
response = requests.get("https://www.udacity.com/courses/all")
soup = BeautifulSoup(response.text)
soup.find_all(class_= "course-summary-card")
강의에서는 타이틀을 찾는 코드를 쓰는데, 다음 방식은 우리가 가져온 데이터에 똑같이 적용할 수 있다.
summaries[0].select_one("h3 a")
가끔 값 자체에 =""과 같은 방식으로 공백인 경우가 있다. 이 경우에 써줄수 있는 방법은 다음과 같다. 일단 태그 이름을 지정해주고, attribute의 이름을 []에 넣어서 검색한다고 한다. 하지만 우리의 경우에는 형식이 달라졌으므로 다음과 같은 방법을 사용했다.
# Extract description
summaries[0].find_all("span", class_="ng-star-inserted")[-1].get_text()
# Find all course summaries, extract title and description
summaries = soup.find_all("div", class_= "course-summary-card")
for summary in summaries:
title = summary.select_one("h3 a").get_text().strip()
description = summary.find_all("span", class_="ng-star-inserted")[-1].get_text()
print("***", title, "***")
print(description)
이 텍스트 데이터를 저장해보자.
# Find all course summaries, extract title and description
courses = []
summaries = soup.find_all("div", class_= "course-summary-card")
for summary in summaries:
title = summary.select_one("h3 a").get_text().strip()
description = summary.find_all("span", class_="ng-star-inserted")[-1].get_text()
courses.append((title, description))
print(len(courses), "course summaries found. Sample:")
print(courses[0][0])
print(courses[0][1])
지금까지 우리가 한것은 웹페이지 스크래핑(Scraping webpage)이라고 불리는 작업이다. (또는 크롤링이라고 불리는 작업이다.) 이러한 스크래핑 작업은 매우 흔한 작업이며, 구글 뉴스는 이러한 작업의 좋은 예시이다.
'Udacity Nanodegree > Natural Language Processing' 카테고리의 다른 글
Text Processing(3) - 텍스트 내에서의 분류/변환작업 (0) | 2019.01.23 |
---|---|
Text Processing(2) - 데이터 전처리(Text Preprocessing) (0) | 2019.01.23 |
NLP의 작업 과정 (0) | 2019.01.20 |
Welcome to the Natural Language Processing Nanodegree (0) | 2019.01.17 |
(Udacity NLP) 시작하기 전 (0) | 2018.12.27 |