★ 아직 많이 부족합니다. 댓글을 통한 가르침 환영입니다. ★

 

이번에는 머신러닝에 대한 포스팅을 해볼까 합니다.

 

저의 개발환경은 [Python 3.5.4 / Pycharm IDE / Anaconda3 ]를 사용 중입니다.

 

하지만, 조금 쉽게 접근하기 위해 머신러닝에 대한 내부 구현이 어떻게 되어있는지 알 필요없이 마이크로소프트의 클라우드에서 제공하는 머신러닝 API를 활용하여 원하는 결과값을 얻도록 해보는 것이 목표입니다.

 

먼저, 마이크로소프트 클라우드 서비스인 Azure(https://portal.azure.com)에 접속합니다.

 

마이크로소프트 계정으로 로그인을 하시면 다음과 같은 페이지가 보이게 됩니다

 

 

여기서 왼쪽에 새로만들기를 누르고, 검색에 Cognitive Service를 입력하면 해당 서비스가 보이는 것을 확인할 수 있습니다.

 

 

Cognitive Service에 대한 부분은 다음 링크에서 더욱 자세하게 살펴보실 수 있습니다.

 

https://azure.microsoft.com/ko-kr/services/cognitive-services/

 

그럼 계속해서 해당 서비스를 만들고, 이용해보도록 하겠습니다.

 

이름과, 구독수준, 사용할 API, 가격은 무료, 위치는 다양하지만 미국 서부 2로 하였고, 리소스 그룹을 정해주고, 대시보드에 고정을 눌러줍니다.

 

 

이렇게 만들면, 대시보드에 Cognitive Service가 나타나게 됩니다.

 

사용할 API는 Computer Vision API로, https://azure.microsoft.com/ko-kr/services/cognitive-services/computer-vision/ 에서 더욱 자세히 확인하실 수 있습니다.

 

이렇게 Cognitive Service를 만들었으면, 다음 화면이 보이게 됩니다.

 

여기서는 사용할 구독 키 발급과 각종 API 레퍼런스 문서, SDK 등을 확인하실 수 있습니다.

 

 

먼저, 코드 작성하기 앞서 API 사용에 필요한 구독 키를 Keys 버튼을 눌러 확인하겠습니다.

 

 

(저의 구독키 중 첫 번째 알파벳을 제외하고 가렸습니다)

 

위나 아래의 둘 중 아무거나 구독 키를 사용하시면 됩니다. 저는 위의 구독키를 활용하도록 하겠습니다.

 

이렇게 구독키를 확인했으면 Computer Vision APi를 활용에 있어 제공되는 튜토리얼 코드를 참고해서 작성하도록 하겠습니다.

 

https://docs.microsoft.com/ko-kr/azure/cognitive-services/computer-vision/quickstarts/python

 

위의 사이트에 들어가시면 Python 3.6으로 작성된 튜토리얼 코드를 확인하실 수 있습니다.

 

1
2
3
4
########### Python 3.6 #############
import http.client, urllib.request, urllib.parse, urllib.error, base64, json
 
subscription_key = '자신의 구독 키'
cs

 

위와 같이 자신의 구독 키로 대체해 준 후,

 

1
uri_base = 'westus2.api.cognitive.microsoft.com'
cs

 

Cognitive API를 만들 때, 미국 서부 2로 설정했으므로 위와 같이 바꿔줍니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
headers = {
    'Content-Type''application/json',
    'Ocp-Apim-Subscription-Key': subscription_key,
}
 
params = urllib.parse.urlencode({
    'visualFeatures''Categories,Description,Color',
    'language''en',
})
 
body = "{'url':'https://upload.wikimedia.org/wikipedia/commons/1/12/Broadway_and_Times_Square_by_night.jpg'}"
 
try:
    conn = http.client.HTTPSConnection(uri_base)
    conn.request("POST""/vision/v1.0/analyze?%s" % params, body, headers)
    response = conn.getresponse()
cs

 

나머지는 동일하게 적어주고, 14번째 줄에 인자값을 설정한 미국 서부의 값인 uri_base로 바꿔줍니다.

 

1
2
3
4
5
6
7
8
9
10
11
  data = response.read().decode('utf-8')
 
    # 'data' contains the JSON data. The following formats the JSON data for display.
    parsed = json.loads(data)
    print ("Response:")
    print (json.dumps(parsed, sort_keys=True, indent=2))
    conn.close()
 
except Exception as e:
    print('Error:')
    print(e)
cs

 

그리고 나머지 코드입니다.

 

저는 튜토리얼에서 제공되는 코드가 동작하지 않아 첫 번째 줄에 .decode('utf-8')을 붙여줌으로써 발생되는 에러를 해결했습니다.

 

출력해보면 이미지의 분석 결과가 출력되는 것을 알 수 있습니다.

 

이렇게 전체 코드가 작성되었는데 분석을 시도한 URL의 이미지를 직접보며, 어떻게 분석되었는지 조금 확인해볼까 합니다.

 

그러기 위해서는 라이브러리 2개를 설치해줍니다.

 

conda install scikit-image 

 

conda install -c conda-forge matplotlib 

 

이 후, try문의 코드를 다음과 같이 수정합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
try:
    conn = http.client.HTTPSConnection('westus2.api.cognitive.microsoft.com')
    conn.request("POST""/vision/v1.0/analyze?%s" % params, body, headers)
    response = conn.getresponse()
    data = response.read().decode('utf-8')
    parsed = json.loads(data)
    print ("Response:")
    #print (json.dumps(parsed, sort_keys=True, indent=2))
    print(parsed['description'])
    img = io.imread('https://upload.wikimedia.org/wikipedia/commons/1/12/Broadway_and_Times_Square_by_night.jpg')
    plt.imshow(img)
    plt.show()
 
cs

 

코드를 실행 해보면

 

 

1
2
3
Response:
{'tags': ['outdoor', 'building', 'street', 'city', 'busy', 'people', 'filled', 'traffic', 'many', 'table', 'car', 'group', 'walking', 'bunch', 'crowded', 'large', 'night', 'light', 'standing', 'man', 'tall', 'umbrella', 'riding', 'sign', 'crowd'],
 'captions': [{'text': 'a group of people on a city street filled with traffic at night', 'confidence': 0.8241405091548035}]}
cs

 

와 같이 이미지를 출력하고, 해당 이미지의 tag 값들과 그 이미지를 분석한 caption 값 그리고 그 확률을 출력하는 것을 확인할 수 있습니다.

 

추가적으로 다른 이미지를 분석하고 싶다면,

 

1
body = "{'url':'원하는 이미지 URL'}"
cs

 

의 URL 부분을 원하는 이미지의 URL로 수정하고

 

1
img = io.imread('원하는 이미지 URL')
cs

 

해당 부분의 URL 또한 수정하여 출력 결과를 확인하시면 됩니다.

 

이렇게 마이크로소프트 클라우드에서 제공하는 cognitive API를 활용해 이미지를 분석해보았습니다.

★ 아직 많이 부족합니다. 댓글을 통한 가르침 환영입니다. ★

 

이번에는 Selenium(셀레니움)을 이용해서 크롤링을 해보겠습니다.

 

Selenium은 기본적으로 Webdriver을 활용하여 웹앱을 테스트하는데 주로 사용됩니다.

 

이전 포스팅에서는 BeautifulSoup을 활용하여 크롤링을 해왔었는데, BeautifulSoup은 유튜브 메인페이지처럼 스크롤을 내리면 계속 추가되는 내용까지 가져오기 어렵기 때문에 이 부분을 Selenium을 통해 가져와보도록 하겠습니다. (무한스크롤이라고 하죠..)

 

Youtube 페이지를 내려가며, 여기에 있는 모든 동영상의 제목을 크롤링해오는 것을 해보도록 하겠습니다.

 

먼저, Selenium을 설치해줍니다.

 

pip install selenium  

 

그리고, Webdriver을 다운받아줍니다.

 

Chrome :  https://sites.google.com/a/chromium.org/chromedriver/downloads 

 

Firefox :  https://github.com/mozilla/geckodriver/releases 

Edge :  https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/

 

저는 chrome으로 진행하겠습니다만, 더 선호하시는 webdriver을 설치하여 진행하시면 됩니다.

 

이후, 편의상 다운받은 webdriver을 코드를 작성하는 directory로 이동시키겠습니다.

 

꼭 이동시키지 않아도 webdriver의 경로를 명시해주면 webdriver가 구동이 됩니다.

 

이제 코드를 작성해보도록 하겠습니다.

 

1
2
3
4
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import time
cs

 

먼저 위와 같이 3개의 라이브러리를 import 해주겠습니다.

 

이유는 아래에 하나하나 설명해가겠습니다.

 

그 다음,

 

1
driver = webdriver.Chrome('webdriver 경로')
cs

 

를 적어주시면 됩니다.

 

만약, 다운로드 받은 webdriver가 같은 폴더 내에 있을 경우에는

 

1
driver = webdriver.Chrome()
cs

 

만 해도 동작이 됩니다.

 

그 다음, 동작 된 webdriver가 실행할 url 주소를 다음과 같이 작성해줍니다.

 

1
2
3
driver.get('https://www.youtube.com/')
 
time.sleep(1)
cs

 

그리고 time 라이브러리를 import 한 이유는, 유튜브 url이 충분히 켜질 시간을 주는 역할을 합니다.

 

다음에는 켜진 youtube 페이지의 html 영역의 body를 스크롤을 충분히 내려주는 과정을 작성하겠습니다.

 

즉, youtube 페이지에 접속해서 스크롤을 계속 내리다보면 영상이 계속 추가로 로드되고

 

계속 더 내리다보면 추가로드 라는 버튼이 활성화되며 이를 클릭하면 영상이 또 추가로 로드가 되는 것을 확인할 수 있습니다.

 

 

 

그럼 이 추가로드 버튼까지 클릭해가며, 동영상이 더 이상 추가되지 않을 때까지 스크롤을 내려보겠습니다.

 

스크롤을 충분히 내려 추가로드 버튼이 보일때까지 내려줍니다.

 

F12 개발자도구를 키고, 추가로드 버튼을 찾아보시면 div class의 아이디가 feed-main-what_to_watch 이고,

 

그 아래 button이 보이는 것을 확인 할 수 있습니다.

 

스크롤을 내리며, 이것을 클릭해 주도록 만들어 스크롤을 더 이상 영상이 로드 안될 때 까지 내려보겠습니다.

 

1
2
3
4
5
6
7
8
9
10
num_of_pagedowns = 50
 
while num_of_pagedowns:
    body.send_keys(Keys.PAGE_DOWN)
    time.sleep(0.3)
    num_of_pagedowns -= 1
    try:
        driver.find_element_by_xpath("""//*[@id="feed-main-what_to_watch"]/button""").click()
    except:
        None
cs

 

위와 같이, from selenium.webdriver.common.keys import Keys를 추가해줌으로써

 

HTML body 영역에다가 pagedown키를 누르게 함으로써 페이지를 내릴 수 있습니다.

 

이렇게 0.3초 간격으로 50번을 내려주면 보통 끝까지 도달합니다.

 

다음으로는 추가로드 버튼이 보이면 클릭되는 부분을 try구문에 적어주었고, 발견되지 않으면 아무것도 동작하지 않도록 했습니다.

 

이렇게 페이지 끝에 도달하면,

 

여기까지 로드 된 HTML을 가져오고 이를 BeautifulSoup으로 분석하겠습니다.

 

1
2
3
html = driver.page_source
soup = BeautifulSoup(html, 'lxml')
titles = soup.find_all('h3')
cs

 

위와 같이 webdriver가 연 url의 html은 page_source를 통해 가져올 수 있고,

 

이를 BeautifulSoup으로 분석합니다. 제목이 h3 태그값에 존재하기에 그 제목값을 모두 찾아줍니다.

 

그리고,

 

1
2
3
4
for title in titles:
    print (title.get_text())
    
driver.close()
cs

 

출력해주면 모든 제목을 가져올 수 있게 됩니다. 마지막에는 close()를 통해 webdriver을 닫아줍니다.

 

 

페이지의 출력 결과

 

1
2
3
4
5
6
7
8
9
10
11
12
7개 지옥, 7번의 재판 [신과 함께: 죄와 벌]
한국인에게 인종차별한 미국인 역관광
국내 언론에서는 다루지 않은 문재인 대통령 혼밥 아무도 몰랐던 그 진실 이야기 감동 사연
피자집 의자에 앉기만 하면~ 고양이가 무릎위로 온다? 고양이를 부르는 요술 의자
[유병재 라이브] 문학의 밤 유행어 짓기 선수권 (with 유규선 문상훈)
[예능연구소 직캠] 트와이스 하트 쉐이커 @쇼!음악중심_20171216 HEART SHAKER TWICE in 4K
리니지m 똘끼 리니지참 피곤해...
롤은 이기려고 하는거 아닙니다. 상대 빡치라고 하는겁니다.
우주하마 배틀그라운드 ♥ LIVE
[ 인피쉰 LIVE ] ( 2017-12-18 월요일 생방송) 안녕하세요! 빨무 스타 스타크래프트 팀플레이 Shin Starcraft
LOL 롤 브실골 미드/원딜 1위. 저격 환영
...(중략)...
cs

위 이미지에서 안보이는 제목은 > 버튼을 클릭하니 동영상이 존재하더군요.

 

이렇게 웹 페이지에서 스크롤을 내린 후 크롤링을 해오는 코드를 작성해보았습니다.

 

아래는 전체 코드 입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import time
 
driver = webdriver.Chrome()
 
driver.get('https://www.youtube.com/')
 
time.sleep(2)
 
body = driver.find_element_by_tag_name("body")
 
num_of_pagedowns = 50
 
while num_of_pagedowns:
    body.send_keys(Keys.PAGE_DOWN)
    time.sleep(0.3)
    num_of_pagedowns -= 1
    try:
        driver.find_element_by_xpath("""//*[@id="feed-main-what_to_watch"]/button""").click()
    except:
        None
 
html = driver.page_source
soup = BeautifulSoup(html, 'lxml')
titles = soup.find_all('h3')
 
for title in titles:
    print (title.get_text())
 
driver.close()
cs

'크롤링' 카테고리의 다른 글

네이버 영화순위 크롤링  (1) 2017.12.17

★ 아직 많이 부족합니다. 댓글을 통한 가르침 환영입니다. ★

 

이번에는 Python을 활용하여 네이버 영화순위를 크롤링해오도록 하겠습니다.

 

제가 분석할 URL은 http://movie.naver.com/movie/sdb/rank/rmovie.nhn 입니다.

 

HTML을 가져와 분석하기 위해, BeautifulSoup4를 활용하겠습니다.

 

 

들어가기 앞서, 제 개발환경은

 

[ Windows 10 64-bit, Python 3.5.4, IDE : Pycharm ]

 

[Anaconda3]를 활용하고 있습니다.

 

자, 그럼

 

가장 먼저, BeautifulSoup4을 설치해보도록 하죠.

 

pip install BeautifulSoup4 

 

 

다음은, URL의 정보를 가져오기 위해 코드를 작성해봅시다.

 

BeautifulSoup을 활용할 경우 코드가 정말 간단히 작성됩니다.

 

1
2
from bs4 import BeautifulSoup
import urllib.request
cs

 

이렇게 두 라이브러리를 import 해줍니다.

 

1
html = urllib.request.urlopen('http://movie.naver.com/movie/sdb/rank/rmovie.nhn')
cs

 

이렇게 URL을 통해 가져온 html 데이터를 BeautifulSoup4를 활용하여 분석하도록 하겠습니다.

 

1
soup = BeautifulSoup(html, 'lxml')
cs

 

여기서, 혹시 에러가 발생한다면

 

pip install lxml 

 

을 설치해주도록 합니다. 다음,

 

1
print (soup)
cs

 

을 통해 출력을 해보면, 네이버 영화 순위 사이트에 해당하는 HTML 데이터가 출력되는 것을 확인할 수 있습니다.

 

사이트 진입 후, F12 개발자도구를 열어 확인할 수 있는 데이터입니다.


그럼 이 URL을 본격적으로 분석해보도록 하겠습니다.

 

1
titles = soup.find_all('td''title')
cs

 

먼저, 각 순위에 해당하는 모든 영화 정보를 titles에 담아옵니다.

 

이렇게 코드를 작성한 이유는,

 

 

 

F12 개발자도구를 확인하여 2017년 12월 17일 기준 1등인 영화 '강철비'라는 텍스트가 위치한 곳이

 

td -> div -> a href 의 텍스트로 위치해있기 때문에, td 클래스의 이름은 title인 것을 가져오도록 작성하였습니다.

 

1
2
3
4
5
6
7
8
9
10
11
<td class="title">
    <div class="tit3">
        <a href="/movie/bi/mi/basic.nhn?code=155665" title="강철비">강철비</a>
    </div>
 
    </td><td class="title">
        <div class="tit3">
            <a href="/movie/bi/mi/basic.nhn?code=160399" title="기억의 밤">기억의 밤</a>
    </div>
 
...(중략)...
cs

 

이렇게 가져오며,

 

여기서

 

<a href="/movie/bi/mi/basic.nhn?code=155665" title="강철비">강철비</a>

 

위 줄의 빨간색의 강철비 텍스트를 가져오기 위해서는

 

1
print (titles[0].find('a').text)
cs

 

와 같이 작성하여 가져올 수 있습니다.

 

그렇다면, 50개의 모든 영화순위를 가져오기 위해 반복문을 작성해보겠습니다.

 

1
2
3
4
5
rank = 1
 
for title in titles:
    print(str(rank) + "위 : " + title.find('a').text)
    rank += 1
cs

 

순위를 명시해주기 위한 rank 변수도 만들어 위와 같이 반복문을 작성하면

 

1
2
3
4
5
6
7
8
9
1위 : 강철비
2위 : 기억의 밤
3위 : 꾼
4위 : 어쌔신: 더 비기닝
5위 : 스타워즈: 라스트 제다이
6위 : 메리와 마녀의 꽃
7위 : 신과함께-죄와 벌
8위 : 오리엔트 특급 살인
...(중략)...
cs

 

이와 같이 2017년 12월 17일 기준의 영화 순위가 출력되게 됩니다.

 

여기서 멈추지 않고 추가로, 각 영화의 링크 주소도 가져와보도록 하겠습니다.

 

위의 영화 이름을 가져왔던 코드에 한 줄을 추가하여

 

1
2
print (titles[0].find('a').text)
print (titles[0].find('a')['href'])
cs

 

다음과 같이 만들어,

 

<a href="/movie/bi/mi/basic.nhn?code=155665" title="강철비">강철비</a>

 

위의 파란색으로 표시된 링크까지 가져올 수 있게 됩니다.

 

1
2
강철비
/movie/bi/mi/basic.nhn?code=155665
cs

 

링크를 완전하게 만들기 위해,

 

1
print ('http://movie.naver.com/' + titles[0].find('a')['href'])
cs

 

다음과 같이 수정하여,

 

1
http://movie.naver.com//movie/bi/mi/basic.nhn?code=155665
cs

 

위와 같은 완전한 링크를 얻어냅니다.

 

그럼 이제 영화 순위와 함께, 영화의 링크도 가져오는 전체 코드를 작성해보도록 하겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
from bs4 import BeautifulSoup
import urllib.request
 
html = urllib.request.urlopen('http://movie.naver.com/movie/sdb/rank/rmovie.nhn')
soup = BeautifulSoup(html, 'lxml')
titles = soup.find_all('td''title')
front_url = 'http://movie.naver.com/'
rank = 1
for title in titles:
    print(str(rank) + " : " + title.find('a').text + ' / link : ' + front_url + title.find('a')['href'])
    rank += 1
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1위 : 강철비 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=155665
2위 : 기억의 밤 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=160399
3위 : 꾼 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=152385
4위 : 어쌔신: 더 비기닝 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=100205
5위 : 스타워즈: 라스트 제다이 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=125488
6위 : 메리와 마녀의 꽃 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=159037
7위 : 신과함께-죄와 벌 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=85579
8위 : 오리엔트 특급 살인 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=154272
9위 : 반드시 잡는다 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=155411
10위 : 이프 온리 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=39440
11위 : 뽀로로 극장판 공룡섬 대모험 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=169349
12위 : 덩케르크 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=146480
...(중략)...
41위 : 무서운 꿈 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=170236
42위 : 역모 - 반란의 시대 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=142210
43위 : 정글 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=158623
44위 : 미옥 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=142317
45위 : 킹스맨: 골든 서클 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=149747
46위 : 극장판 포켓몬스터 너로 정했다! / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=165722
47위 : 쥬라기 월드: 폴른 킹덤 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=154285
48위 : 1급기밀 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=149504
49위 : 러브 액츄얼리 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=36843
50위 : 원더 / link : http://movie.naver.com//movie/bi/mi/basic.nhn?code=151196
 
2017-12-17
cs

 

이렇게 BeautifulSoup을 통해 몇 줄 안되는 코드로 영화 순위를 가져오는 코드를 작성해보았습니다.

'크롤링' 카테고리의 다른 글

Selenium(셀레니움)을 활용한 크롤링  (2) 2017.12.18

+ Recent posts