2019. 8. 20. 17:13ㆍ프로젝트/인스타그램 크롤링
준비
-운영체제 : Windows 10
-언어 : Python
-웹 드라이버 : chromedriver.exe
프로그램 실행 과정
1. 인스타그램 해시태그를 크롤링합니다.
2. 검색어를 입력하면 검색어에 관한 게시물의 작성자 ID와 해시태그를 수집합니다.
3. 수집 후 csv(txt) 파일로 변환합니다.
인스타그램은 JavaScript를 사용하여 페이지를 스크롤할 때 새로운 게시글을 불러오는 방식이라
selenium라이브러리를 추가로 사용했습니다.
selenium은 웹 드라이브를 사용하는 라이브러리이며 반응형 사이트 파싱에 사용합니다.
꼭 크롬 드라이버를 사용할 필요는 없지만 크롬을 사용하고 있기 때문에 크롬 드라이버를 다운로드하였습니다.
크롬 버전은 브라우저 오른쪽 위 브라우저 옵션 - 도움말 - 정보에서 아래와 같이 확인 가능합니다.
아래 사이트에서 버전에 맞는 드라이버를 다운로드할 수 있습니다.
검색
인스타그램에서 '아이유'를 검색하면 위와 같이 주소가 변합니다.
/ 와 / 사이에 검색어가 들어가기 때문에 주소 사이에 검색어를 넣어줬습니다.
검색어를 URL에 사용할 수 있도록 urllib.parse.quote를 사용합니다.
search = input("검색어를 입력하세요 : " )
search = urllib.parse.quote(search)
url = 'https://www.instagram.com/explore/tags/'+str(search)+'/'
Selenium 사용해보기
selenium라이브러리를 설치했다면 웹 드라이버를 사용할 수 있습니다.
다운로드한 드라이버는 작업 중인 폴더에 넣고 아래와 같이 경로를 설정했습니다.
driver = webdriver.Chrome('chromedriver.exe')
driver.get(url)
sleep(5)
드라이버를 실행시킨 후 5초간 sleep을 줍니다. 페이지가 완전히 로드된 후 코드를 진행해야 하기 때문입니다.
페이지가 완전히 로드되기 전에 코드를 진행시키면 오류가 발생합니다.
인스타그램 게시글은 스크롤을 내릴 때마다 추가로 로드되기 때문에
selenium의 자동 스크롤 기능을 사용했습니다.
SCROLL_PAUSE_TIME = 1.0
reallink = []
while True:
pageString = driver.page_source
bsObj = BeautifulSoup(pageString, "lxml")
for link1 in bsObj.find_all(name="div",attrs={"class":"Nnq7C weEfm"}):
title = link1.select('a')[0]
real = title.attrs['href']
reallink.append(real)
title = link1.select('a')[1]
real = title.attrs['href']
reallink.append(real)
title = link1.select('a')[2]
real = title.attrs['href']
reallink.append(real)
last_height = driver.execute_script("return document.body.scrollHeight")
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
sleep(SCROLL_PAUSE_TIME)
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
sleep(SCROLL_PAUSE_TIME)
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
else:
last_height = new_height
continue
우선 변수로 스크롤의 속도를 설정해줍니다.
for문과 BeautifulSoup로 게시물들의 주소를 가져옵니다.
'Nnq7C weEfm' 클래스의 'a' 태그들을 가져왔습니다.
페이지의 height를 비교해서 스크롤하고 height값이 같으면 스크롤을 멈춥니다.
1.0으로 설정했지만 컴퓨터 사양에 따라서 시간을 조절할 필요가 있습니다.
페이지를 불러오는 속도가 느리면 스크롤이 끝에 다다랐다고 판단하고 스크롤을 종료합니다.
크롤링
위와 같이 인스타그램의 게시물들은 모두 고유 주소를 가지고 있습니다.
스크롤을 통해 모든 게시물의 주소 값을 알게 되었으니 저장된 주소에서 ID값과 해시태그를 가져올 수 있습니다.
위와 같이 게시물에서 파싱할 부분을 선택합니다.
아이디와 해시태그가 있으니 저 부분을 가져옵니다.
for i in range(0,reallinknum):
csvtext.append([])
req = Request('https://www.instagram.com/p'+reallink[i],headers={'User-Agent': 'Mozilla/5.0'})
webpage = urlopen(req).read()
soup = BeautifulSoup(webpage,"lxml",from_encoding='utf-8')
soup1 = soup.find("meta",attrs={"property":"og:description"})
reallink1 = soup1['content']
reallink1 = reallink1[reallink1.find("@")+1:reallink1.find(")")]
reallink1 = reallink1[:20]
if reallink1 == '':
reallink1 = 'Null'
csvtext[i].append(reallink1)
for reallink2 in soup.find_all("meta",attrs={"property":"instapp:hashtags"}):
reallink2 = reallink2['content']
csvtext[i].append(reallink2)
for 문에 주소가 저장된 리스트를 넣고 돌리고 BeautifulSoup로 아이디와 해시태그를 가져왔습니다.
아이디는 메타태그의 property가 'og:description'
해시태그는 메타태그의 property가 'instapp:hashtags' 인 것을 가져와서 새로운 리스트에 넣어줬습니다.
아래와 같이 태그의 수만큼 아이디가 반복되도록 넣었습니다.
ID1 | 아이유 |
ID1 | 호텔 |
ID1 | 델루나 |
ID2 | 호텔델루나 |
Data to CSV
모든 작업이 끝나면 정리된 리스트를 CSV 형식으로 저장합니다.
파일 형식도 .csv로 바꿨지만 인코딩 오류가 생겨서 .txt 형식으로 저장 후
.csv형식으로 다시 저장했습니다.
data = pd.DataFrame(csvtext)
data.to_csv('insta.txt', encoding='utf-8')
결과, 활용
아이유를 검색한 결과 중 일부입니다.
게시물의 수가 많다보니 시간이 너무 오래걸리는 단점이 있었습니다.
해결을 위해 멀티프로세싱을 활용해볼 예정입니다.
Gephi와 같은 데이터 분석 프로그램을 활용해서
수집한 데이터를 분석 할 수 있습니다.