2018년 9월 4일 화요일

페이스북 좋아요 횟수 가져 오기


단일 페이지 어플리케이션의 웹 크롤링 (https://blog.naver.com/yoojchul/221333353523) 에 소개된 방법 대로 페이스북도 읽을 수 있습니다.   아래 프로그램은  환경운동연합의 페이스북 글과 그 글에 달린 좋아요’, ‘댓글’ , ‘공유의 횟수를 가져 옵니다.



 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# -*- coding: utf-8 -*-
from selenium import webdriver
import time
from bs4 import BeautifulSoup
import sys

fp = webdriver.FirefoxProfile("C:/Users/rcjcyoo/AppData/Roaming/Mozilla/Firefox/Profiles/y07d4b26.selenium")
driver = webdriver.Firefox(fp)   # keckodriver in the same directory with this script
driver.implicitly_wait(3)
driver.get('https://www.facebook.com')

driver.find_element_by_xpath("//input[@name='email']").send_keys('xxxxx@xxxx.com')
driver.find_element_by_xpath("//input[@name='pass']").send_keys('xxxxxx')

login = driver.find_element_by_xpath("//input[@value='로그인']")
login.click()

driver.get('https://www.facebook.com/kfem.or.kr/')

last_height = driver.execute_script("return document.body.scrollHeight")
count = 0
while True:
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    count += 1
    time.sleep(3)

    # Calculate new scroll height and compare with last scroll height
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height or count > 3:
        break
    last_height = new_height

non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd)

soup = BeautifulSoup(driver.page_source, 'html.parser')
wrappers = soup.findAll("div", {"class":"_5pcr userContentWrapper"})

for w in wrappers:
    cnt = w.find("div", {"class":"_5pbx userContent _3576"}).find("p").text
    try:
        print(cnt.translate(non_bmp_map))
    except UnicodeEncodeError:
        print("**unknown char**")
    attaches = w.findAll("div", {"class" : "_36_q"})
    for a in attaches:
        print(a.text)
    print()

라인 78selenium를 통해 firefox를 실행하는 과정입니다.  실행에 프로필을 포함하는데 그 이유는  페이스북 접속시에 나타나는  귀찮은 firefox 알림창을 막기 위함입니다.  위 프로그램 실행 전에 “firefox.exe –p”firefox 프로필 관리자를 실행하고 프로필 만들기를 클릭해서 “selenium”를 만듭니다.  프로그램에서 사용할 때는 프로필 디렉토리 이름을 지정해야 하는데  보통 <home 디렉톨>/AppData/Roaming/Mozilla/Firefox/Profiles/xxxxx.selenium입니다.  



해당 프로필로 firefox를 실행후 주소창에서 “about:config”을 입력하고 dom.push.enableddom.webnotifications.enabledfalse로 바꿉니다.  selenium를 통해 firefox를 실행할 때 프로필을 만들지 않으면  설정은 남아 있지 않고 항상 초기화 상태입니다.


 라인 1213에서 아이디와 암호를 넣고 라인 1516에서 로그인 버튼을 클릭합니다. 라인 18로 환경운동연합 페이스북으로 넘어 갑니다.

라인 20부터 31까지는 반복적인 화면 스크롤 다운과 같은 역활을 합니다.  라인 2028은 페이스북 화면 y축 길이를 가져 오고 라인 23은 그 길이 만큼 스크롤 다운합니다. 다시 화면 y축 길이를 가져 와서 예전 길이가 같은 때, 즉 더 이상 화면이 내려가지 않을 때 루프에서  빠져 나와 스크롤 다운을 중단합니다.   스크롤 다운 횟수가 4 이상이 되어도 중단합니다.   라인 25에서 스크롤 다운과 길이를 가져 오는 사이에 3초를 쉽니다.  쉬는 시간이 짧으면 웹브라우저의 느린 스크롤 다운 반응으로 인해  y축 길이가 같은 경우가 생겨 끝이 아닌데도 불구하고 의도하지 않게 루프가 끝날 수가 있습니다.

페이스북에서 글과 좋아요횟수를 찾을 때는 beautifulsoup 패키지를 이용합니다.  라인 35에서  BeautifulSoup 첫번째 인수가 driver.page_source인데  이것이 웹브라우저에 뿌려진 DOM 데이터입니다.

게시글과 좋아요div 태그에 둘러 쌓있는데  먼저 클래스 이름 “_5pcr userContentWrapper”wrapper가 있습니다. wrapper 안에  게시글과 좋아요을 이끄는 다른 div태그가 있으므로 프로그램에서 “_5pcr userContentWrapper”를 찾습니다.   이름이 특이한데 별도로 soup.prettify()로 출력한 아래 그림에서 확인합니다.  



게시글은 div태그에 클래스 이름은 "_5pbx userContent _3576”인데 이 역시 미리 soup.prettify() 결과에서 확인합니다. 


  
좋아요 div 태그에 클래스 이름은  "_36_q"입니다.  좋아요외에 같은 class 이름으로 댓글공유가 있습니다.



이러한 태그와 클래스 이름을 근거로 라인 3947까지 게시글과 좋아요횟수를 찾을 수 있습니다.  클래스 이름은 201894일 기준이고 이후 달라질 수 있습니다. 게시글 출력시에 특수 문자로 인해 간혹 UnicodeEncoderError이 발생합니다. 출력하기 전에 translate(non_bmp_map)으로 0x10000이상의 코드는 0xfff0로 변환해서 에러가 발생하지 않도록 합니다.

아래 그림은 프로그램 결과로서 게시글과 함께 게시글의 좋아요횟수를 표시합니다.






댓글 없음:

댓글 쓰기