GitHub - jinhyeook/InstaTripRecommender

프로젝트 개요

주제 : 인스타그램 게시물을 기반으로 사용자에게 여행지를 추천하는 앱 구현

팀 : 5인 1조

담당 역할 : 인스타그램 게시물 데이터 수집, 추천 시스템 구현

기간 : 2023.11 ~ 2023.12

사용 기술 및 툴 : Python, Selenium, BeautifulSoup, Jupter Notebook, MySQL, PyQt, Flask

담당 기능 및 구현 내용

본 프로젝트에서 사용자 맞춤 장소 추천 시스템 개발을 담당함.

자연어 처리 기반 키워드 추출부터 유사도 분석, 추천 결과 도출까지의 전 과정을 구현함.

추천을 위한 데이터를 확보하기 위해 인스타그램 게시물 크롤링 기능을 직접 구현함.

Seleum과 BeautifulSoup을 이용해 인스타그램의 특정 위치 게시물 본문 데이터를 자동 크롤링을 진행함.

게시물의 내용, 날짜, 좋아요 수, 장소, 태그, 이미지 URL(게시물 첫번째 이미지) 등 다양한 정보를 수집.

from selenium import webdriver
from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By

import time
import re

def insta_searching(word): # 장소에 대한 게시물이 모여있는 곳으로 이동
    url="<https://www.instagram.com/"+str(word)+"/>"
    return url

def select_first(driver): # 첫 번째 게시물 선택
    first = driver.find_element(By.CSS_SELECTOR, "div._aagw")
    first.click()
    time.sleep(3)

def get_content(driver):
    
    html=driver.page_source
    soup=BeautifulSoup(html,'lxml')
    try:
        content = soup.select('div._a9zs')[0].text # 내용
    except:
        content=''
    
    tags=re.findall(r'#[^Ws#,WW]+',content)
    
    data = soup.select('time._aaqe')[0]['datetime'][:10] # 날짜
    
    try:
        like=soup.select('span.html-span.xdj266r.x11i5rnm.xat24cr.x1mh8g0r.xexx8yu.x4uap5.x18d9i69.xkhd6sd.x1hl2dhg.x16tdsg8.x1vvkbs')[0].text # 좋아요 수
    except:
        like=0
    
    try:
        place = soup.select('div._aaqm')[0].text # 장소
    except:
        place=''
        
    try:   
        img_element = driver.find_element(By.CSS_SELECTOR,'._aatk .x5yr21d.xu96u03.x10l6tqk.x13vifvy.x87ps6o.xh8yej3') 
        img_src = img_element.get_attribute('src') # 이미지
    except:
        img_src=''
        
    data=[content,data,like,place,tags,img_src]
    
    return data

def move_next(driver): # 다음 게시물 이동
    right = driver.find_element(By.CSS_SELECTOR, "div._aaqg._aaqh")
    right.click()
    time.sleep(3)
    
#--------------------------------------------------------------------------------

from urllib.parse import quote_plus
from selenium.webdriver.common.by import By

# Chrome 웹 드라이버를 시작
driver = webdriver.Chrome()
driver.get('<https://www.instagram.com>')
time.sleep(3)

email = '아이디'
input_id = driver.find_element(By.NAME, 'username')
input_id.clear()
input_id.send_keys(email)

password = '비밀번호'
input_pw = driver.find_element(By.NAME, 'password')
input_pw.clear()
input_pw.send_keys(password)
input_pw.submit()

time.sleep(5)

word = input("검색어를 입력하세요: ")
url = insta_searching(word)

driver.get(url)
time.sleep(15)

select_first(driver)

results = []
target = 201 #크롤링할 게시물 수
for i in range(target):
    try:
        data = get_content(driver)
        results.append(data)
        move_next(driver)
    except:
        time.sleep(2)
        move_next(driver)

driver.close()

크롤링한 데이터 MySQL DB에 저장 (엑셀파일 저장 → 엑셀파일 DB저장)

import pandas as pd
results_df = pd.DataFrame(results)
results_df.columns = ['content', 'date', 'like','place','tags','img_src']

name = input("제목을 입력해주세요 : ")
results_df.to_excel(name+'.xlsx')

from sqlalchemy import create_engine

# 엑셀 파일 경로
excel_file_path = name+'.xlsx'

# MySQL 데이터베이스 연결 정보
db_username = ''
db_password = ''
db_host = ''
db_name = ''
db_port = ''

# 테이블 이름
table_name = name

# 엑셀 파일을 DataFrame으로 읽기
excel_df = pd.read_excel(excel_file_path)

# MySQL 연결 엔진 생성
engine = create_engine(f'mysql://{db_username}:{db_password}@{db_host}:{db_port}/{db_name}')

# DataFrame을 MySQL 테이블에 저장
with engine.connect() as connection:
    # 테이블이 존재하지 않으면 생성
    connection.execute(f'''
        CREATE TABLE IF NOT EXISTS {table_name} (
            content VARCHAR(500),
            date DATE,
            like_count INT,
            place VARCHAR(50),
            tags VARCHAR(500),
            img_src VARCHAR(500)
        );
    ''')
    
    # 데이터를 테이블에 추가 (if_exists='replace' 옵션을 사용하면 기존 데이터를 대체)
    excel_df.to_sql(table_name, con=engine, if_exists='replace', index=False)

print(f'DataFrame이 MySQL 테이블로 저장되었습니다: {table_name}')