본문 바로가기
지덕이의 데이터 분석/데이터 분석 스킬

[파이썬Python] 인스타그램 해쉬태그(#) 검색결과 크롤링하기

by 지표덕후 2021. 2. 21.
반응형

★ 댓글로 주신 의견 반영하여 코드는 지속적으로 수정하고 있습니다. 수정된 부분은 아래 본문에 일일이 표시해두었으니 참고해주세요. 댓글 주신 모든 분들 감사합니다.

 

셀레니움의 기초


이 포스팅에서 소개하는 크롤링은 파이썬 Selenium 라이브러리를 사용합니다. 그러니 셀레니움에 대한 기초가 없는 분들은 아래 포스팅을 먼저 읽어보셔요.

 

 

미국 주식 재무제표 크롤링으로 배우는 파이썬 Selenium 기초

웹 크롤링(혹은 웹 스크래핑)을 하는 여러 가지 방법 중에 파이썬 셀레니움을 활용하는 방식은 난이도가 좀 있는 편입니다. 저 역시 가급적 Selenium 없이 크롤링 하는 걸 선호하지만 어떤 유형의

mokeya.tistory.com

 

 

 

코딩의 결과


기본 컨셉은, 인스타그램에서 특정 해시태그를 검색했을 때 나오는 게시물들을

나 대신 하나하나 누르면서 게시물 내의 정보를 긁어오는 머신을 만든다고 생각하시면 됩니다.

게시물을 긁어와랏, 머신!

 

 

 

 

이 작업으로 수집하는 정보는 인스타그램 게시물 본문과 게시일, 좋아요 수, 장소, 해시태그입니다.

아래와 같은 형태의 테이블로 저장되고 엑셀로 읽기, 쓰기가 가능합니다.

순번 content date like place tags
0 저녁에 뭘할까? 하다 잡채가 급 땡기네~냉장고에 시금치와 느타리버섯 조금남은것 양파 당근 있고 고기가없네 ㅋ 떡볶이 만들려고 사놓은 사각어묵이  있어 어묵잡채로 ~~#집밥 #맛스타그램 #어묵잡채 #요즘시금치가맛있다 #잡채 #foodstagram #cookstagram #koreanfood 2021-01-22 5,423 Koreatown, Los Angeles ['#짚신매운갈비찜', '#spicyfood', '#매운갈비찜', '#갈비찜', '#kfood짚신매운갈비찜', '#Canada', '#koreanfood']

 

 

작업환경


1) 파이썬3.7(32bit)

2) 파이썬IDE는 JetBrain의 Pycharm

3) 크롤링 머신은 크롬 확장 프로그램의 도움으로 작동하기 때문에 사전에 크롬이 설치되어 있어야 합니다.

4) 또한 크롬드라이버(ChromeDriver)라는 파일(.zip)을 다운받아서 앞으로 작성할 파이썬 코드(.py)가 저장될 폴더에 함께 넣어두어야(=압축 해제) 합니다.

  ① 먼저 우리 크롬 브라우저의 버전을 확인합니다.

       크롬 브라우저 우상단의 메뉴 > 도움말 > Chrome정보(아래 스샷 참고)

 

② 아래 링크된 페이지에서 우리 버전 및 운영체제에 맞는 크롬 웹드라이버를 다운 받습니다.

https://chromedriver.chromium.org/downloads

 

③ 다운 받은 압축파일의 내용물을 코드가 저장된() 폴더에 압축 해제합니다.

반응형

 

 

코드

* 2022/04/03 게시물 크롤링 함수 정의하는 코드 스니펫 수정


크롤링에 필요한 여러 패키지들을 불러옵니다.

저혼자 인스타 로그인해서 게시물을 일일이 눌러가며 데이터를 긁어오는 이 똘똘한 머신은

셀레니움 패키지(+ 크롬 웹드라이버)가 있기에 가능한 겁니다.

# 필요 패키지 호출
from selenium import webdriver
from bs4 import BeautifulSoup
import time
import re
import time

 

 

 

 

금번 파이썬 코딩은 머신이 수행할 행동 하나하나를 분절적으로 나누어서

부분동작을 별개의 함수로 정의하는 것에서 시작합니다(국민체조 드립을 치고 싶지만 참습니다).

먼저, 내가 원하는 키워드를 받아서

해당 키워드 검색 결과 페이지의 url을 생성(반환=return)하는 함수를 정의.

# 함수 정의: 검색어 조건에 따른 url 생성
def insta_searching(word):
    url = "https://www.instagram.com/explore/tags/" + str(word)
    return url

 

 

 

 

다음으로, 검색 결과 페이지에서 첫 번째 게시물을 클릭하는 함수를 정의.

인스타그램 서버에서 우리 머신이 (무언가 불순한 의도를 가지고) 마우스를 갈기는 것처럼 인식되지 않도록,

또 데이터를 긁어오는 시간을 충분히 확보할 수 있도록,

다음 행동과의 시차를 time.sleep() 메서드로 구현.

# 함수 정의: 열린 페이지에서 첫 번째 게시물 클릭 + sleep 메소드 통하여 시차 두기
def select_first(driver):
    first = driver.find_elements_by_css_selector("div._9AhH0")[0]
    first.click()
    time.sleep(3)

 

 

 

 

클릭해 들어간 게시물에서 내가 원하는 정보,

본문 내용과 작성일자, 좋아요 수, 위치 정보, 해시태그를 가져오는 함수 정의.

인스타의 프론트 코드가 변경되어 '좋아요 수'가 수집되지 않는 오류를 정정(2021/08/20)

인스타 마크업의 selector가 변경되어 몇몇 정보가 수집되지 않는 오류 정정(2022/04/03)

# 함수 정의: 본문 내용, 작성일자, 좋아요 수, 위치 정보, 해시태그 가져오기
## 2022/04/03 전체적으로 수정
import re
from bs4 import BeautifulSoup

def get_content(driver):
    html = driver.page_source
    soup = BeautifulSoup(html, 'lxml')
    # 본문 내용
    try:
        content = soup.select('div.MOdxS')[0].text
    except:
        content = ''
    # 해시태그
    tags = re.findall(r'#[^\s#,\\]+', content)
    
    # 작성일자
    date = soup.select('time._1o9PC')[0]['datetime'][:10]
    
    # 좋아요
    try:
        like = soup.select('section.EDfFK.ygqzn')[0].findAll('span')[-1].text
    except:
        like = 0
    # 위치
    try:
        place = soup.select('div.M30cS')[0].text
    except:
        place = ''

    data = [content, date, like, place, tags]
    return data

 

 

 

 

한 게시물에서 소기의 목적을 달성(=원하는 정보 긁어오기)한 후

다음 게시물로 넘어가는(= 게시물 오른쪽의 화살표 클릭하여 페이징) 함수 정의.

time.sleep() 메서드로 마찬가지로 다음 행동과의 시차를 확보.

다음 게시물로 넘어가는 버튼의 프론트 코드가 변경되어 이를 반영하였습니다(2022/01/11).

# 함수 정의: 첫 번째 게시물 클릭 후 다음 게시물 클릭
def move_next(driver):
    right = driver.find_element_by_css_selector("div.l8mY4.feth3") # 2022/01/11 수정
    right.click()
    time.sleep(3)

 

 

 

 

아래 코드는 본격적으로 머신에게 일을 시키는 코드입니다.

위에서 정의한 각 부분동작(=함수)들이 포함되어 있습니다.

다만 함수로 정의하지 않은 몇 가지 행동들은 별도로 코딩을 해야 하는데,

가령. 최초에 인스타그램에 접속하여 로그인을 하기 위한 코드라라든지

검색어를 입력 받는 코드(아래 스샷), 크롤링 할 게시물의 수를 정해주는 코드 같은 것들입니다.

 

코드를 수행하면 인스타그램 메인이 뜨면서 자동으로 로그인이 되고,

위와 같이 검색 키워드를 입력하면,

이제 머신이 순차적으로 부분동작을 수행하면서

게시물 하나하나의 데이터를 정성스럽게 긁어(크롤링)올 겁니다.

페이지가 완전히 로드된 후 첫 게시물을 클릭할 수 있도록 sleep()의 파라미터 수정(2022/01/11).

# 크롤링 시작
"""
driver.get(url)을 통해 검색 페이지 접속하고,
target 변수에 크롤링할 게시글의 수를 바인딩
"""

# 크롬 브라우저 열기
driver = webdriver.Chrome('chromedriver.exe')

driver.get('https://www.instagram.com')
time.sleep(3)

# 인스타그램 로그인을 위한 계정 정보
email = '인스타그램 로그인 아이디'
input_id = driver.find_elements_by_css_selector('input._2hvTZ.pexuQ.zyHYP')[0]
input_id.clear()
input_id.send_keys(email)

password = '인스타그램 로그인 비번'
input_pw = driver.find_elements_by_css_selector('input._2hvTZ.pexuQ.zyHYP')[1]
input_pw.clear()
input_pw.send_keys(password)
input_pw.submit()

time.sleep(5)

# 게시물을 조회할 검색 키워드 입력 요청
word = input("검색어를 입력하세요 : ")
word = str(word)
url = insta_searching(word)

# 검색 결과 페이지 열기
driver.get(url)
time.sleep(8) # 코드 수행 환경에 따라 페이지가 로드되는 데 시간이 더 걸릴 수 있어 8초로 변경(2022/01/11)

# 첫 번째 게시물 클릭
select_first(driver)

# 본격적으로 데이터 수집 시작
results = []
## 수집할 게시물의 수
target = 10000
for i in range(target):

    try:
        data = get_content(driver)
        results.append(data)
        move_next(driver)
    except:
        time.sleep(2)
        move_next(driver)

print(results[:2])

 

 

 

 

부디 코드가 정상적으로 작동하여 크롤링 무사히 마치고,

데이터가 예쁘게 들어간 엑셀 파일 떡하니 생성되어 있길 바랍니다.

# 결과를 데이터프레임으로 저장
# 2022/04/03 수정
import pandas as pd
from datetime import datetime

date = datetime.today().strftime('%Y-%m-%d')

results_df = pd.DataFrame(results)
results_df.columns = ['content','date','like','place','tags']
results_df.to_excel(date + '_about '+word+' insta crawling.xlsx')

이번 크롤러 제작에 사용한 셀레니움 패키지를 조금만 응용하면 마케팅에 활용할 수 있는 다양한 데이터를 수집할 수 있습니다. 가령 아래처럼요:

파이썬 웹스크래핑: 구글 플레이 스토어 앱 리뷰 크롤링
반응형

댓글23

  • 순풍 2021.03.05 13:14

    코딩을 더욱 배워보고 싶은 마음이 드네요!
    답글

  • 코딩초보 2021.06.21 18:01

    소스대로 하니까 selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"div._9AhH0"} 이런 오류가 뜨는 데 경로가 잘못된걸까요? 도움 주시면 감사하겠습니다!
    답글

    • 지표덕후 2021.06.28 21:08 신고

      오류가 난 부분이, “첫 페이지에서 첫 게시물 클릭”인데요. 첫 페이지를 의미하는 코드가 div._9AhH0 에서 다른 것으로 바뀐 것 같아요. 서비스 업데이트를 하거나 하면 소스코드가 변경될 수 있거든요. PC 인스타 화면에서 F12를 눌러 개발자도구를 여셔서 직접 element 코드를 확인하시는 방법이 있는데요. 이 글이 도움이 될 수 있을 것 같아요. https://mainia.tistory.com/2408

  • 익명 2022.01.08 21:01

    비밀댓글입니다
    답글

    • 지표덕후 2022.01.11 00:56 신고

      문의해주셔서 감사해요, 본문에 코드 수정하고 수정 사유도 기재해두었습니다. 아마 "list의 인덱스가 가용범위를 넘어섰다"라는 에러메시지를 만나셨을 거 같은데요. first.click 전에 페이지가 완전히 로드될 수 있는 시간을 확보했어야 되는데 제가 시간을 너무 촉박하게 잡았었나봐요. sleep()의 파라미터를 8초로 넉넉하게 변경하였습니다. 더불어 move_next 함수 정의하는 부분도 코드 수정이 있으니 꼭 함께 참고해주세요.

  • 익명 2022.02.07 20:47

    비밀댓글입니다
    답글

    • 익명 2022.02.07 20:49

      비밀댓글입니다

    • 지표덕후 2022.02.07 21:26 신고

      제가 제대로 읽지 않고 답변을 드렸네요. 지금 코드 그대로 복사해서 수행해봤는데 이상 없이 크롤링되더라구요ㅠ 혹시 "검색어를 입력하세요 : "가 떴을 때 키워드 입력을 하셨을까요?

    • 익명 2022.02.07 23:12

      비밀댓글입니다

    • 익명 2022.02.07 23:15

      비밀댓글입니다

    • 지표덕후 2022.02.08 10:03 신고

      https://0ver-grow.tistory.com/1021
      이 글이 도움이 될 수 있을 것 같아요. "div._9AhH0" 태그가 완전히 로드되기 전에 크롤링을 시도하다가 발생하는 에러인 것 같은데요.

      제 본문 <코드> 꼭지 세 번째 코드 스니펫 first = 윗줄에,

      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.support import expected_conditions as EC
      from selenium.webdriver.common.by import By
      WebDriverWait(driver, timeout=5).until(EC.presence_of_element_located((By.TAG_NAME, "div._9AhH0")))
      print("div._9AhH0 태그를 찾았습니다.")

      이 코드라인 한 번 추가해보시겠어요?

  • 아아 2022.03.03 01:07

    안녕하세요 키워드 검색 후 모든 창바꿈이 지나고 결과값 저장 단계에서 아래와 같은 오류가 발생했는데, 이유를 알 수 있을까요??


    Traceback (most recent call last):
    File "C:/Users/00/PycharmProjects/python/cj/insta.py", line 115, in <module>
    results_df.columns = ['content','date','like','place','tags']
    File "C:\Users\00\PycharmProjects\python\venv\lib\site-packages\pandas\core\generic.py", line 5596, in __setattr__
    return object.__setattr__(self, name, value)
    File "pandas\_libs\properties.pyx", line 70, in pandas._libs.properties.AxisProperty.__set__
    File "C:\Users\00\PycharmProjects\python\venv\lib\site-packages\pandas\core\generic.py", line 769, in _set_axis
    self._mgr.set_axis(axis, labels)
    File "C:\Users\00\PycharmProjects\python\venv\lib\site-packages\pandas\core\internals\managers.py", line 214, in set_axis
    self._validate_set_axis(axis, new_labels)
    File "C:\Users\00\PycharmProjects\python\venv\lib\site-packages\pandas\core\internals\base.py", line 69, in _validate_set_axis
    raise ValueError(
    ValueError: Length mismatch: Expected axis has 0 elements, new values have 5 elements

    답글

    • 저도요 ㅠ 2022.03.31 04:53

      저도 같은 오류인데 혹시 한 번만 답변 가능할까요??

    • 지표덕후 2022.04.03 20:35 신고

      알려주셔서 감사합니다. 위의 코드뭉치 중 네 번째 코드뭉치를 수정해두었으니 코드수정하셔서 다시 크롤링 해보시겠어요? 제가 했을 때는 정상적으로 수집 되고 저장 됩니다.

  • 익명 2022.03.31 04:51

    비밀댓글입니다
    답글

    • 지표덕후 2022.04.03 20:36 신고

      인스타에서 마크업언어를 수정해둔 데 대한 조치를 했는데요. 이 조치로 언급하신 문제가 해결될지는 모르겠습니다. 일단 포스팅 본문의 수정된 코드 참고하셔서 다시 한 번 크롤링해보시겠어요?

    • 히히호호 2022.04.06 10:48

      안녕하세요 위에 댓글입니다.
      저때 하도 급해서 html을 아무것도 모르는 제가 공부해서 마크업언어를 수정했네용 ㅋㅋ 감사합니당 ㅎㅎ

  • vv 2022.04.16 23:57

    위 코드로 돌려서 생성된 파일을 열어보니 칼럼 이름만 출력되고 내용이 출력되지 않습니다. 데이터를 불러오지 못하는 것 같은데 어떻게 수정해야 할까요?
    답글

  • 코린이 2022.05.30 20:07

    감사합니다ㅠㅠ 너무잘돼서 깜짝 놀랐어요!!
    답글

  • 익명 2022.06.02 19:41

    비밀댓글입니다
    답글

  • HH 2022.06.08 18:05

    안녕하세요. 덕분에 프로그램을 잘 돌아가는데 마지막에 저장이 안되는 듯합니다.
    Traceback (most recent call last):
    File "d:\startcoding\insta\insta_Keyword copy.py", line 127, in <module>
    results_df.columns=['content','data','like','place','tags']
    File "d:\startcoding\insta\lib\site-packages\pandas\core\generic.py", line 5588, in __setattr__
    return object.__setattr__(self, name, value)
    File "pandas\_libs\properties.pyx", line 70, in pandas._libs.properties.AxisProperty.__set__
    File "d:\startcoding\insta\lib\site-packages\pandas\core\generic.py", line 769, in _set_axis
    self._mgr.set_axis(axis, labels)
    File "d:\startcoding\insta\lib\site-packages\pandas\core\internals\managers.py", line 214, in set_axis
    self._validate_set_axis(axis, new_labels)
    File "d:\startcoding\insta\lib\site-packages\pandas\core\internals\base.py", line 69, in _validate_set_axis
    raise ValueError(
    ValueError: Length mismatch: Expected axis has 0 elements, new values have 5 elements

    (insta) D:\startcoding>[20616:17832:0608/175940.661:ERROR:gpu_init.cc(481)] Passthrough is not supported,
    GL is disabled, ANGLE is

    이유가 뭘까요?
    답글