미국 주식 데이터 수집 #9 미국 주식 국가 정보 가져오기(본사 위치)

 벌써 미국 주식 데이터 수집 시리즈 9탄입니다. 오늘은 각 종목의 국가 정보를 가져오는 코드를 살펴보겠습니다. 국내에서도 퀀트 투자를 진행할 때 본사가 국내가 아닌 경우는 제외하는 경우가 많죠. 이는 실적 발표에 대한 신뢰도가 떨어지는 국가(ex. 중국😅)가 있기 때문입니다. 최근 쿠팡이 나스닥에 상장한 것처럼 미국 주식 시장이라고 하더라도 다양한 국가의 기업들이 상장되어 있습니다. 투자에 활용할 수 있도록 국가 정보도 함께 관리하기로 하였습니다.

 

1.가져올 데이터 대상

 역시나 가장 익숙한 Yahoo Finance에서 정보를 찾아보았습니다! Profile 탭도 API로 제공을 해주면 좋을 것 같지만, 문서를 뒤져봐도 Profile 탭에 대한 정보를 제공하는 API는 없었습니다. 그렇다면 직접 웹사이트에서 스크래핑을 해야겠죠. 이전에 Sector 정보를 스크래핑할 때도 봤었던 페이지와 동일하기 때문에 그대로 진행해보겠습니다.

 

Yahoo Finance의 Profile 탭

 위 캡처 화면을 보면 기업의 주소 정보와, 전화번호, 홈페이지 주소가 기재되어 있습니다. 그 중 저희가 가져올 정보는 본사의 주소 정보인 'South Korea'입니다. 차근차근 코드를 살펴보겠습니다.

 

2.페이지 정보 가져오기

# 필요 라이브러리 import
import requests
from bs4 import BeautifulSoup
import re
import pandas as pd
import yahoo_fin.stock_info as si

# 페이지 정보 가져오기
url = "https://finance.yahoo.com/quote/{}/profile?p={}".format('CPNG', 'CPNG')
html = requests.get(url).text
soup = BeautifulSoup(html, "html.parser")
print(soup)

 

 Beautiful Soup로 위 캡처 화면의 페이지 주소에서 Html 소스를 긁어왔습니다. 출력된 결과를 보면, 아주 복잡하게 모든 소스코드가 잘 가져온 것을 확인할 수 있습니다.

 

 

3.국가 정보 접근하기

 위에서 Profile 탭의 전체 Html 소스를 가져왔는데, 그 중에서 저희가 필요한 정보에 접근해야 합니다. Profile 탭에서 F12(개발자 모드)를 누르고 Element를 확인해보면, 어디에 필요한 정보가 있는지 확인할 수 있습니다. soup 객체에서 다양한 방식으로 필요한 정보를 찾아갈 수 있겠지만, 저는 태그의 class로 한 번 조회해보겠습니다.

 

Profile 탭의 전체 소스코드

location = soup.select('p[class = "D(ib) W(47.727%) Pend(40px)"]')[0]
print(location)

"""
print 결과
<p class="D(ib) W(47.727%) Pend(40px)" data-reactid="8">
<!-- react-text: 9 -->Tower 730,570<!-- /react-text -->
<br data-reactid="10"/><!-- react-text: 11 -->Songpa-Daero<!-- /react-text -->
<br data-reactid="12"/><!-- react-text: 13 -->Seoul 05510<!-- /react-text -->
<br data-reactid="14"/><!-- react-text: 15 -->South Korea<!-- /react-text -->
<br data-reactid="16"/><a class="C($linkColor)" data-reactid="17" href="tel:82261505422">82 2 6150 5422</a>
<br data-reactid="18"/><a class="C($linkColor)" data-reactid="19" href="http://www.coupang.com" rel="noopener noreferrer" target="_blank" title="">http://www.coupang.com</a></p>
"""

<p> 태그 하나 안에 줄 바꿈으로 나누어져서 표기가 되는 형식이네요. 이를 리스트 형태로 나누어서 보겠습니다.

 

 

location_list = list(location.stripped_strings)
print(location_list)

"""
['Tower 730,570', 'Songpa-Daero', 'Seoul 05510', 'South Korea', '82 2 6150 5422', 'http://www.coupang.com']
"""

이제 원하는 정보에 접근하기가 더 쉬워졌네요. 위에 출력 결과에서 South Korea에 해당하는 것만 뽑아내면 되겠네요! 그런데 실제로 전체 주식을 대상으로 작업을 돌려보니 약간의 문제가 있었습니다. 바로 종목마다 주소 정보의 개수도 다르고, 전화번호가 없는 경우도, 홈페이지가 없는 경우도 있어서 리스트 내에서의 위치가 고정적이지 않는 것입니다.

 

그래서 소스코드가 많이 더러워지기는 했지만, 저는 아래와 같이 처리했습니다.

    try :
        location = list(soup.select('p[class = "D(ib) W(47.727%) Pend(40px)"]')[0].stripped_strings)
        
        if 'http' not in location[-1] and not bool(re.search(r'\d', location[-1])) :
            country = location[-1]
        elif 'http' not in location[-1] or not bool(re.search(r'\d', location[-2])) :
            country = location[-2]
        else :
            country = location[-3]
    except :
        country = ''

 간략하게 설명을 드리자면 아래 조건 순으로 국가 정보를 찾는 것입니다.

 

1.리스트의 마지막이 홈페이지도 아니고, 전화번호도 아닌 경우 → 마지막을 국가 정보로 간주

2.리스트의 마지막이 홈페이지가 아니거나, 리스트의 끝에서 두번째가 전화번호가 아닌 경우 → 끝에서 두 번째 항목을 국가로 간주

3.리스트의 마지막이 홈페이지고, 리스트의 끝에서 두번째가 전화번호인 경우  끝에서 세 번째 항목이 국가로 간주

 

룰이 조금 지저분하긴 하지만, 이렇게 해서 6000개의 종목을 돌려보니 정상적으로 국가 정보를 가져올 수 있었습니다😁

국가가 United States인 종목이 5181개, 그 외가 1288개 입니다. 이번에 추가한 정보도, 이번 주 데이터부터 추가해서 업로드 될 예정입니다.

 

 


공감댓글, 공유는 큰 힘이 됩니다!

도움이 되셨다면 널리널리 알려주세요😉

 

 

댓글()