개발/Python

[Python] Instagram Crawling

삽쟁이 2021. 5. 13. 12:59
반응형

시작하기

Instagram의 경우, 로그인 후 "https://www.instagram.com/explore/tags/[태그문자]" 접속 시, 해당 [태그문자]로 올라온 게시물들을 확인 할 수 있다. 따라서 특정태그문자에 올라온 다양한 게시물들의 정보를 확보하여 다른 태그문자들과의 연관성 및 해당 게시물들의 이미지를 확보 할 수 있다.

개발환경

  • MAC OS Big Sur 11.2.3
  • Python3
  • Chrome 버전 90.0.4430.93(공식 빌드) (x86_64)
  • Chrome Driver 90.0.44

개발준비

사용한 패키지 및 도구

  • selenium, BeautifulSoup, pandas
pip3 install selenium pip3 install BeautifulSoup pip3 install pandas

 

  • ChromeDriver 설치 (자신이 로컬에 설치된 Chrome버전과 동일한 버전으로...)
    ChromeDriver - WebDriver for Chrome - Downloads
    Current Releases If you are using Chrome version 91, please download ChromeDriver 91.0.4472.19 If you are using Chrome version 90, please download ChromeDriver 90.0.4430.24 If you are using Chrome version 89, please download ChromeDriver 89.0.4389.23 If you are using Chrome version 88, please
    chromedriver.chromium.org

     

개발내용

소스코드를 확인하기 전에 먼저 어떠한 방법으로 어떠한 데이터를가져올지를 파악해야한다.

https://www.instagram.com/explore/tags/이직/ 를 통해 #카페 라는 해시태그를 사용한 게시물들을 가져온 화면이다.
(약 113,255개의 게시물)

여기서 특정 게시물을 클릭 하면 해당 게시물의 상세정보를 가져 올 수 있다.

 

해당 게시물에서 가져오길 원하는 데이터를 정리한다. (빨간색 테두리)

  1. 게시물의 이미지
  2. 게시물의 Description
  3. Hash Tag
  4. Like 수.
  5. 게시물의 위치정보(게시물에 따라서 위치정보를 입력한 게시물은 또 가져 올 수 있다.)

자! 이제 어떻게, 어떠한 데이터를 가져올지 파악했다. 실전으로 가즈아!

전체 Python 소스코드
더보기
from selenium import webdriver
import time
import re
from bs4 import BeautifulSoup
import pandas as pd


def searching(word):
    url = 'https://www.instagram.com/explore/tags/'+word
    return url

driver = webdriver.Chrome("./chromedriver")

def click_first(driver):
    first = driver.find_element_by_css_selector('#react-root > section > main > article > div:nth-child(3) > div > div:nth-child(1) > div:nth-child(1) > a > div.eLAPa > div._9AhH0')
    first.click()
    time.sleep(3)

def next_page(driver):
    next_page = driver.find_element_by_css_selector('body > div._2dDPU.CkGkG > div.EfHg9 > div > div > a._65Bje.coreSpriteRightPaginationArrow')
    next_page.click()
    time.sleep(3)

def get_content(driver):

    # 1. 현재 게시글 html 정보 가져오기
    html = driver.page_source
    soup = BeautifulSoup(html, 'lxml')


    # 2. 본문 내용 가져오기
    # 본문 내용이 없을 수 있으므로 예외 처리구문을 이용
    try:
        content = soup.select('div.C4VMK > span')[0].text
    except:
        content = ''

    # 3. 작성 일시, 좋아요 수 , 위치 정보 가져오기
    # 해쉬 태그는 정규 표현식을 이용해 가져온다.
    tags = re.findall(r'#[^\s#,\\]+', content)  

    #  작성일자 정보 가져오기
    date = soup.select('time._1o9PC.Nzb55')[0]['datetime'][:10]

    #  좋아요 수 가져오기
    # 예외처리구문.
    try:
        # print(soup.select('div.Nm9Fw.zV_Nj > span')[0].text)
        like = soup.select('div.Nm9Fw > a > span')[0].text   
    except:
        like = 0
    # 위치정보
    # 예외 처리구문
    try: 
        place = soup.select('div.M30cS')[0].text
    except:
        place = ''
    # 위치정보
    # 예외 처리구문
    try: 
        img = img = soup.select('div._97aPb img')[0]['src']
        print(img)   
    except:
        img = ''
    # 4. 저장하기
    data = [content, date, like, place, tags, img]
    return data


# 인스타그램 접속하기
driver.get('http://www.instargram.com')

#로딩하는데 시간이 걸릴 수 있으므로 3초간 대기
time.sleep(3)
insta_id = 'ID'   
input_id = driver.find_elements_by_css_selector('input._2hvTZ.pexuQ.zyHYP')[0]

password = 'PW!' 
input_pw = driver.find_elements_by_css_selector('input._2hvTZ.pexuQ.zyHYP')[1]

input_id.send_keys(insta_id)
input_pw.send_keys(password)

first = driver.find_element_by_css_selector("#loginForm > div.Igw0E.IwRSH.eGOV_._4EzTm.kEKum > div:nth-child(3)")
first.click()

time.sleep(5)

word = 'pet'
url = searching(word)

# 검색페이지 접속
driver.get(url)
time.sleep(3)

# 첫 번째 게시글 열기
click_first(driver)

#크롤링 결과를담을 리스트 생성
result = [ ]


# 여러 게시글 수집하기
target = 1000     # 크롤링할 게시글 수
for i in range(target):
    # 게시글 수집에 오류 발생시 5초 대기후, 다음 게시글로 넘어가도록 예외처리 구문 활용
    try:
        data = get_content(driver)    # 게시글 정보 가져오기
        result.append(data)
        next_page(driver)
    except:
        time.sleep(5)
        next_page(driver)
result = pd.DataFrame(result)
result.to_csv('/Users/kimyoungho/python/sample.csv', index=False, encoding="utf-8-sig")
print(result)

 

 

개발 완료?된 소스코드이다. 방법이 생소한거 뿐 작성된 소스코드는 간단한 편이다.

내용은 소스코드 실행 시, 자동으로 크롬을 실행하고 인스타를 접속및 로그인, 크롤링까지 자동적으로 되도록 하는 내용이다.

소스코드와 개발시 난항을 겪은 부분에 대해서 설명해보겠다.

실행 Flow

  1. Chrome실행 후, 인스타그램(http://www.instargram.com) 접속
  2. 로그인 후, https://www.instagram.com/explore/tags/이직/ 접속
  3. 첫 번째 게시물 클릭 → 데이터 수집 → 다음 게시물로 넘어가기 → 반복
#크롬 드라이버를 통해 크롬을 실행하고 인스타를 접속
driver = webdriver.Chrome("./chromedriver")
#이때 https로 접속하면...  크롬에서 보안관련 팝업이 나타나서..자동진행에 방해가 되니 http로 접속하자
driver.get('http://www.instargram.com')


......

#크롬 드라이버를 통해 크롬을 실행하고 인스타를 접속
driver = webdriver.Chrome("./chromedriver")
#이때 https로 접속하면...  크롬에서 보안관련 팝업이 나타나서..자동진행에 방해가 되니 http로 접속하자
driver.get('http://www.instargram.com')

실행결과

 

자동으로 로그인 하는 장면도 넣고 싶으나...이건...내 개인정보 ㅠㅠ.... 넣을 수 가 없었다. 
자동으로 게시물을 넘기는 장면만 넣었다. 동영상에서 볼 수 있듯 하나의 게시물을 3초에 한번씩 넘기면서 데이터를 수집하는 중이다.

아래 파일은 pet이라는 검색어로 얻은 데이터이다.(이거 올려도 되는건가...?ㅎㅎ)

 

sample_pet.csv
0.23MB

 

 

마무리

필자는 인스타를 하지 않아서.. 사실 인스타 자체를 파악하는데 더 많은 시간이 들었던거 같다. 인스타의 구조를 좀더 잘 파악하고 있었으면 시간을 낭비하지 않았을텐데...

크롤링이라는 것도 사실 개념만 알고 있었지 이렇게 실전에서 사용하는게 처음이라서 사실 처음에 앞길이 막막했다...(잘 사용하지 않는 언어 + 잘 모르는 개념 = 지옥)

또한 크롤링 시, 해당 html의 class나 태그명을 통해서 크롤링을 하는게..기본인데.. Instagram이 업데이트를 열심히 하는지 자주 바뀌는거 같다...

driver.find_element_by_css_selector('body > div._2dDPU.CkGkG > div.EfHg9 > div > div > a._65Bje.coreSpriteRightPaginationArrow')
soup.select('div._97aPb img')
#div._97aPb img 이런 값이 업데이트 되면 다시 찾아서 수정해줘야 함 ㅡㅡ...

바뀌고 나서 해당 값을 찾을때 개발자 도구로 찾아도 좋지만 Python3의 디버깅 모드로 한줄한줄 디버깅하면서 찾는게 정확한거 같다...(시간은 많이 들지만.. 확실)

 

마지막으로 여러가지 키워드로 얻은 데이터를 워드클라우드로 시각한 자료까지 공유하면서 마무리 찡긋 >_o

이직 키워드
서울 시청 키워드(카메라 사러 많이 오나 보다 ㅇ,ㅇ)

반응형