안녕하세요. "생각의 웹"입니다.
이번 포스팅에서는 facebook의 graph API(https://developers.facebook.com/tools/explorer/)를 이용해 특정 fan page에 게시된 feed 글들을 word cloud로 만들어 보았습니다.
분석 대상 fan page: https://www.facebook.com/VisionMobile
참고 삼아 이 회사는 모바일 앱 및 IoT 관련 산업 및 개발자 동향을 분석해 인사이트 리포트를 제공하는 영국 회사로 깔끔한 시각화 (visualization) 과 핵심을 관통하는 분석으로 평소 많은 도움을 받고 있습니다.
코드 설명에 앞서, facebook의 경우 주기적으로 access token를 발급 받아서 유효한 값을 query parameter로 전송해야만 정상적으로 결과를 얻을 수 있습니다.
자세한 사항은 doc (https://developers.facebook.com/docs/graph-api?locale=ko_KR) 를 참고하시기 바랍니다.
1. feed data를 가져오는 class 만들기
facebook의 특정 page에서 feeds를 가져오기 위해 PsyCharm 혹은 pip 로 'requests', 'urllib3' 를 설치 후 다음과 같이 구현했습니다.
import requests
import json
import facebook
import urllib3
import urllib3.contrib.pyopenssl # due to https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning
urllib3.contrib.pyopenssl.inject_into_urllib3()
urllib3.disable_warnings()
class FacebookRequester:
base_url = 'https://graph.facebook.com/'
version = 'v2.3'
content = []
def __init__(self, token):
self.access_token = token
self.page = 'me'
def setPage(self, page):
self.page = page
def getFeeds(self, limit, times):
fields = 'feed.limit(%s)' % limit
url = '%s/%s/%s?fields=%s&access_token=%s' % \
(self.base_url, self.version, self.page, fields, self.access_token)
counter = 0
print url
while counter < times:
response = requests.get(url).json()
print response
try:
content = response['feed']['data']
paging = response['feed']['paging']
except KeyError: # in case of retrieving by next page
content = response['data']
paging = response['paging']
#print content
#print paging
self.content = self.content + content
next_page_url = paging['next']
if not next_page_url:
break
else :
counter += 1
url = next_page_url
#print url
return self.content
상기 코드에서 유심히 볼 부분은 urllib3 입니다.
이 라이브러리가 없으면 python 2.* 에서 https 로 전송 시도 시 TLS 보안 관련 결함이 있기 때문에 insecure platform warning 과 함께 전송이 되지 않습니다. 따라서 관련 가이드 (https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning) 에 따라 필요한 warning skip code가 추가되었습니다.
두 번째로 facebook은 한번의 요청으로 가져올 수 있는 데이터 양이 정해져 있기 때문에 그 다음 데이터를 가져올 수 있도록 paging property의 next attribute에 다음 요청의 URL 를 제공합니다. 따라서 다음 요청 시에는 이 값을 사용하도록 구현했습니다.
2. feed 가져와서 word 추출하기
import os.path import json import sys import nltk import jsonreader from prettytable import PrettyTable from fb_requester import FacebookRequester ## # Get feeds using facebook graph API # def get_feeds(): ACCESS_TOKEN = '' requester = FacebookRequester(ACCESS_TOKEN) requester.setPage('VisionMobile') feeds = requester.getFeeds(100, 5) return feeds ## # Tokenize all feed messages # def tokenize(feeds): feed_texts = [] for feed in feeds: try: feed_message = feed['description'] # message attribute contains URL but description doesn't feed_texts.append(feed_message) except KeyError: #print feed # if feed has no message field continue tokens = [] for s in feed_texts: tokens += nltk.tokenize.word_tokenize(s.lower()) return tokens ## # Get stemmed list # def get_stemmed_list(tokens): from nltk.corpus import stopwords stop_words = stopwords.words('english') + ['.', ',', '--', '\'s', '?', ')', '(', ':', '\'', '\'re', '"', '-', '}', '{', u'—', 'rt', 'http', '%', 'co', '@', '#', '/', u'…', u'#', u';', u'amp', u't', u'co', u']', u'[', u'`', u'`', u'&', u'|', u'\u265b', u"''", u'$', u'//', u'/', u'%', u'via', u'...', u'!', u'``', u'http'] from nltk.stem import PorterStemmer stemmer = PorterStemmer() stemmed = [] for token in tokens: # try to decode token try: decoded = token.decode('utf8') #print decoded except UnicodeError: decoded = token if decoded is '' or decoded in stop_words: continue stem = stemmer.stem(decoded) #print stem # Skip a few text. I don't know why stopwords are not working :( #skip facebook things if stem.find(u'facebook.com') > 0: continue #skip http things elif stem.find(u'http') >= 0: #print stem continue else: stemmed.append(stem) return stemmed def write_file(filename, lines): f = file(filename, 'w') for word in lines: try: f.write(word.encode('utf-8') + '\n') except UnicodeEncodeError, e: print 'Encoding error ' + word + '\n' f.close() # Simple test feeds = get_feeds() tokens = tokenize(feeds) print tokens stemmed = get_stemmed_list(tokens) print stemmed write_file('feed-word.txt', stemmed)
이 코드는 앞서 포스팅한 tweet으로 word cloud 만들기 코드와 거의 유사하며 tweeter와 facebook의 JSON shema 차이 부분만 변경되었으니 참고해 보시기 바랍니다.
이처럼 양대 SNS 서비스인 tweeter 와 facebook에서 추출한 비정형 데이터에서 문자열 추출을 통해 분석하는 예제를 수행해 보았습니다.
이제는 다양한 이유로 충분한 데이터를 모으려면 제약이 심한 관계로 아주 작은 데이터를 가지고 한 실습에 불과 하지만 이와 같은 방식으로 데이터를 모으고 분석할 수 있는 기반을 경험했다는 점에서 의의를 두고 싶습니다.
이상입니다.
감사합니다.
행복한 하루 되시길!
'Web of Intelligence > Small_Data' 카테고리의 다른 글
[Data Analysis] 아이 등하교 알림 데이터 분석 (0) | 2016.05.16 |
---|---|
A Butterfly of the Dawn: "레 미제라블 등장 인물 관계 분석을 통한 임계 사회에서의 나비 효과 통찰' (0) | 2015.04.17 |
Python 2.7 + NLTK를 windows 8 설치 시 한글 경로 문제 해결 방법 (0) | 2015.03.31 |
Tweet 분석해 word cloud 만들기 (4) | 2015.03.26 |
Python 2.7 + NLTK windows 8.1 (64bit)에 설치하기 (2) | 2015.03.24 |