본문 바로가기

문돌이 존버/코딩연습

동적 페이지 수집(Instagram) using Selenium

반응형

이 코드는 개인적으로 학습용으로 만든 노트에 불과합니다. 연세대학교 서중원님의 github를 그대로 참조해 공부했습니다. 감사합니다.

import sys
!{sys.executable} -m pip install selenium
# 가상의 브라우저를 띄우기 위해 selenium 패키지 import
import selenium
from selenium import webdriver
from selenium.webdriver.common.by import By

# selenium을 활용해 브라우저를 직접 띄우는 경우, 실제 웹서핑을 할때처럼 로딩시간이 필요함
# 로딩시간 동안 대기하도록 코드를 구성하기위해 time 패키지 import
import time

from bs4 import BeautifulSoup
import requests
import urllib

# http://chromedriver.chromium.org/ 크롬 드라이버 설치 후 경로 지정
chrome_options = webdriver.ChromeOptions()

# 브라우저에 임의로 User-agent 옵션을 넣어 Python 코드로 접속함을 숨김
chrome_options.add_argument('--user-agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"')

driver = webdriver.Chrome(executable_path = r"C:\Users\User\chromedriver.exe", chrome_options=chrome_options)

URL = "https://www.instagram.com/"
driver.get(URL)

# 실제 페이지가 불러와지는 시간을 고려해 sleep(SEC) 함수로 기다리는 시간 지정
time.sleep(5)

# click() 함수로 원하는 요소(태그) 클릭
driver.find_element(By.CLASS_NAME, "izU2O").find_element(By.TAG_NAME, "a").click()
time.sleep(5)

# 아이디와 비밀번호를 브라우저에서 직접 입력해도 됨
ID = "....."
PW = "....."
driver.find_element(By.NAME, "username").send_keys(ID)
driver.find_element(By.NAME, "password").send_keys(PW)
time.sleep(2)

driver.find_element(By.CLASS_NAME, "L3NKy").click()
time.sleep(5)

driver.find_element(By.CLASS_NAME, "mt3GC").find_elements(By.TAG_NAME, "button")[1].click()
time.sleep(5)

keyword = "#손흥민"
search_form = driver.find_element(By.CSS_SELECTOR, "#react-root > section > nav > div._8MQSO.Cx7Bp > div > div > div.LWmhU._0aCwM > input")
search_form.send_keys(keyword)
time.sleep(5)

search_url = driver.find_element(By.CLASS_NAME, "fuqBx").find_element(By.TAG_NAME, "a").get_attribute("href")
driver.get(search_url)
time.sleep(5)

# 수집된 게시물 개수를 저장할 변수 선언
post_count = 0

# 게시물 내용을 저장할 파일을 생성
# 파일명에는 "#"을 포함할 수 없으므로 제거
f = open("instagram_post_" + keyword.replace("#", "") + ".txt", "w", encoding = "utf-8")

# 인스타그램 게시물은 스크롤을 계속 내려야 모든 게시물 확인 가능
# 몇 번 스크롤을 내리면서 게시물을 수집할지 지정
# 게시물이 양이 많을수록 스크롤 횟수 증가
scroll_limit = 2

# 수집된 전체 게시물을 저장할 리스트 생성
# 중복된 게시물 수집 방지
total_post_list = []

for i in range(scroll_limit+1):
    # 현재 내려진 스크롤 횟수 출력
    print("Scroll 횟수 :", i, end="\r")
    time.sleep(5)
    # 현재 화면상에 출현한 게시물 모두를 불러와 리스트에 저장
    post_list = driver.find_elements(By.CLASS_NAME, "_9AhH0")
    # 이미 수집된 게시물이 있는지 확인하고 새로운 게시물만 리스트에 저장
    post_list = [post for post in post_list if post not in total_post_list]
    # 수집할 게시물을 수집된 전체 게시물 리스트에 추가
    total_post_list += post_list
    # FOR 문을 활용해 게시물 지정을 반복 (1.~4. 반복)
    for post in post_list:
        try:
            # 1. 포스팅 이미지 클릭
            post.click()
            time.sleep(7)
            # 2. 포스팅 본문 텍스트
            try:
                content = driver.find_element(By.CLASS_NAME, "C4VMK").text
                content = content.replace("\n", " ")
                print(content)
                f.write(content + "\n")
            except:
                None
            # 3. 수집한 포스트 개수 
            post_count += 1
            # 4. 팝업창 닫기
            driver.find_element(By.CLASS_NAME, "ckWGn").click()
        except:
            continue
    time.sleep(5)        
    # 스크롤을 내려 추가 게시물 보기
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(5)
f.close()

print("> 수집한 총 게시물 개수 :", post_count)

driver.close()

# 파일에 저장된 게시글 내용 확인
f = open("instagram_post_" + keyword.replace("#", "") + ".txt", encoding="utf-8")
for post in f.read().split("\n")[:]:
    print(post.strip())
f.close()

아래는 코드를 돌린 결과입니다.

 

728x90
반응형