LiJell's 성장기

__08.data_analyzing_crawling_instagram (인스타그램 1편) 본문

Bigdata/Web Crawling

__08.data_analyzing_crawling_instagram (인스타그램 1편)

All_is_LiJell 2022. 1. 17. 18:29
반응형
 

__09.data_analyzing_visualizing_instagram (인스타그램 2편)

인스타그램 1편 크롤링/전처리: https://lime-jelly.tistory.com/47 인스타그램 3편 시각화/지도: https://lime-jelly.tistory.com/50 ''' Add/Modified on Jan 18 2022 ''' 이전 과정: https://lime-jelly.tistor..

lime-jelly.tistory.com

 

__10.data.analyzing_map_instagram(인스타그램 3편)

인스타그램 1편 크롤링/전처리: https://lime-jelly.tistory.com/47 인스타그램 2편 전처리/시각화: https://lime-jelly.tistory.com/48 파일 받아오기 주소 : https://github.com/Play-with-data/datasalon/tree/..

lime-jelly.tistory.com

8. 인스타그램 크롤링 (instagram crawling)

8.1. 필요한 라이브러리 가져오기

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from bs4 import BeautifulSoup

import pandas as pd
import numpy as np
import time

8.2. 인스타그램 접속 후 로그인 하기

ser = Service('../chromedriver/chromedriver.exe')
driver = webdriver.Chrome(service = ser)

url = 'https://www.instagram.com/'
driver.get(url)
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(3)

8.3. 인스타그램 검색결과 URL 만들어서 접속

def insta_searching(word):
    url = 'https://www.instagram.com/explore/tags/{}/'.format(word)
#     url = 'https://www.instagram.com/explore/tags/' + word # 이것도 가능
    return(url)

8.4. 검색결과 페이지 접속하기

word = '제주도맛집'
url = insta_searching(word)
driver.get(url)
time.sleep(3) # 페이지가 진행되기전에 page_source를 가져오면 오류가 나와서 delay를 줌

8.5. 화면 첫번째 게시글 선택하기

from selenium.webdriver.common.by import By

def select_first(driver):
    # 웹페이지에 접속해서 첫번째 게시글 해당하는 tag 선택해줘
    first = driver.find_element(By.CSS_SELECTOR, 'div._9AhH0') 
    first.click()
    time.sleep(3)

select_first(driver)

8.6. html 정보 가져오기

# 가져올 정보 ['content','data','like','place','tags']
html_insta = driver.page_source

soup = BeautifulSoup(html_insta, 'html.parser')
soup
'''
생략
'''

8.6.1. content

import unicodedata # mac에서 작성한 글 깨지지 않게

content = soup.select('div.ZyFrc div.C4VMK > span')[0].text
content = unicodedata.normalize('NFC', content) # 깨지는 글씨 위해

content
'''
'<광고>온가족이 즐길 수 있는 제주갈비국수!!💕✔손소독제 항시 배치(입장시 입구부터 손소독제 마스크 착용후 입장 가능합니다🥰)▪️오픈시간: 07:30 - 17:00▪️전화: 064-782-5105▪️제주시 구좌읍 해맞이해안로 2284▪️매주 화요일 휴무산도롱맨도롱#제주맛집 #제주도맛집 #제주아쿠아플라넷#표선맛집 #성산맛집 #성산일출봉맛집 #구좌읍맛집 #구좌맛집 #비자림맛집 #안돌오름 #광치기해변맛집 #제주고기국수#제주도고기국수 #성산아침식사'
'''

8.6.2. tags

8.6.2.1. 정규식 확인하기
import re

print('hello\n')
print('hello')
print(r'hello\n')
print('hello')
# r 은 글자 그래로 인식하게 해줌
'''
hello

hello
hello\n
hello
'''
8.6.2.2. tags 가져오기
tags = re.findall(r'#[^\s#,\\]+',content)
tags
'''
['#제주맛집',
 '#제주도맛집',
 '#제주아쿠아플라넷',
 '#표선맛집',
 '#성산맛집',
 '#성산일출봉맛집',
 '#구좌읍맛집',
 '#구좌맛집',
 '#비자림맛집',
 '#안돌오름',
 '#광치기해변맛집',
 '#제주고기국수',
 '#제주도고기국수',
 '#성산아침식사']
'''

8.6.3. date

date = soup.select('time._1o9PC.Nzb55')[0]['datetime'][:10]
type(date) # str
date
'''
'2022-01-16'
'''

8.6.4. likes

likes = soup.select('a.zV_Nj > span')

8.6.5. place

place = soup.select('a.O4GlU')[0].text
place = unicodedata.normalize('NFC', content) # 깨지는 글씨 위해

8.7. html 정보 모아오기 def 만들기

def get_content(driver):
    html_insta = driver.page_source
    soup = BeautifulSoup(html_insta, 'html.parser')

    try:
        content = soup.select('div.ZyFrc div.C4VMK > span')[0].text
        content = unicodedata.normalize('NFC', content) # 깨지는 글씨 위해
    except:
        content = " "

    try:
        tags = re.findall(r'#[^\s#,\\]+',content)
    except:
        tags = " "

    date = soup.select('time._1o9PC.Nzb55')[0]['datetime'][:10]

    try:
        likes = soup.select('a.zV_Nj > span')[0].text
    except:
        likes = 0

    try:
        place = soup.select('a.O4GlU')[0].text
        place = unicodedata.normalize('NFC', content) # 깨지는 글씨 위해
    except:
        place = ""

    data = [content, date, likes, place, tags]

    return(data)
  • 확인해보기
mylist = get_content(driver)
mylist
'''
['<광고>온가족이 즐길 수 있는 제주갈비국수!!💕✔손소독제 항시 배치(입장시 입구부터 손소독제 마스크 착용후 입장 가능합니다🥰)▪️오픈시간: 07:30 - 17:00▪️전화: 064-782-5105▪️제주시 구좌읍 해맞이해안로 2284▪️매주 화요일 휴무산도롱맨도롱#제주맛집 #제주도맛집 #제주아쿠아플라넷#표선맛집 #성산맛집 #성산일출봉맛집 #구좌읍맛집 #구좌맛집 #비자림맛집 #안돌오름 #광치기해변맛집 #제주고기국수#제주도고기국수 #성산아침식사',
 '2022-01-16',
 0,
 '',
 ['#제주맛집',
  '#제주도맛집',
  '#제주아쿠아플라넷',
  '#표선맛집',
  '#성산맛집',
  '#성산일출봉맛집',
  '#구좌읍맛집',
  '#구좌맛집',
  '#비자림맛집',
  '#안돌오름',
  '#광치기해변맛집',
  '#제주고기국수',
  '#제주도고기국수',
  '#성산아침식사']]
'''

8.8. crawling def 만들기

def insta_crawling(word, n):

    url = insta_searching(word)
    driver.get(url)
    time.sleep(8) # 페이지가 진행되기전에 pagesource를 가져오면 오류가 나와서 delay를 줌


    # 첫 사진 선택
    select_first(driver)
    time.sleep(8)



    # 다음 넘어가기
    # target = n
    # n = 크롤링할 게시글 수
    results = []
    # n 대신 target을 넣어줘도 됨
    for i in range(n):
        try:
             # contents 수집
            data = get_content(driver)
            results.append(data)
            move_next(driver)

        except:
            time.sleep(2)
            move_next(driver)

    return(results)

8.9. 데이터 저장

results_df = pd.DataFrame(results)
results_df.columns = ['content','data','like','place','tags']
results_df.to_excel('./files/1_crawling_jejudoMatJip.xlsx')
  • 위 방법으로 여러 데이터를 만들어보자

8.10. 여러 데이터 통합

jeju_insta_df = pd.DataFrame( [ ] )

folder = './files/'
f_list = ['1_crawling_jejudoMatJip.xlsx', '1_crawling_jejudoGwanGwang.xlsx', '1_crawling_jejuMatJip.xlsx', '1_crawling_jejuYeoHang.xlsx']
for fname in f_list:
    fpath = folder + fname
    temp = pd.read_excel(fpath)
    jeju_insta_df = jeju_insta_df.append(temp)

jeju_insta_df.columns =['content','data','like','place','tags']

# 중복 데이터 제거하고 저장
jeju_insta_df.drop_duplicates(subset = [ "content"] , inplace = True)
jeju_insta_df.to_excel('./files/1_crawling_raw.xlsx', index = False)
반응형
Comments