코딩코딩코딩

인스타그램 해시태그 크롤링 및 분석 - 4 본문

파이썬/텍스트마이닝

인스타그램 해시태그 크롤링 및 분석 - 4

hanshow113 2020. 7. 27. 15:30

지난 번 마지막 코드에서  인스타그램 pc버전에서는 중간에 뜬금없는 날짜의 게시물이 올라와서 다음 게시글의 시간과 비교하는 코드를 넣었었습니다.

이렇게 해보니 코드 효율성이 너무 떨어서 시간이 배로 걸려 코드를 수정했습니다.

다음 게시글의 timestamp를 확인하는 것이 아니라 전 게시물의 것을 확인해서 비교했습니다. 전 게시물 같은 경우에는 date_list라는 리스트에 이미 날짜를 변환해서 넣어놨기 때문에 날짜를 다시 timestamp로 변환하는 과정을 거친 후, timestamp 기준 하루(86400) 이상 차이가 나면 pass하도록 했습니다.

 

추가적으로 계정 명에 shared on instagram 같은 것이 포함돼서 수정하는 코드도 포함했습니다.

 

def to_timestamp(std_date):
    date_string = std_date
    date =datetime.strptime(date_string, "%Y.%m.%d")
    time_tuple = date.timetuple()
    std_timestamp = time.mktime(time_tuple)
    return int(std_timestamp)

 

 

def date_based_crawling(std_date):
    id_list.clear()
    like_list.clear()
    tag_list.clear()
    link_list.clear()
    date_list.clear()
    month_list.clear()
    day_list.clear()
    
    
    post_linkx = post_link[popularPostSum():]    # 스크롤 내리면서 모은 데이터 중 인기 게시물은 제외시킴
    num_of_postx = len(post_linkx)
    

    std_timestamp = to_timestamp(std_date)
    # 기준 날짜를 지나면 크롤링이 멈추도록 작동
    
    for i in tqdm_notebook(range(num_of_postx)):
        req = Request("https://www.instagram.com" + post_linkx[i], headers={'User-Agent': 'Mozila/5.0'})
        postpage = urlopen(req).read()
        

        post_body = bs(postpage, 'lxml', from_encoding='utf-8')
        post_core = post_body.find('meta', attrs={'property':"og:description"})
        contents = post_core['content']

        # break할 시간 비교
        posttxt = str(postpage)    
        timestamp = int(posttxt[posttxt.find('taken_at_timestamp')+20 : posttxt.find('taken_at_timestamp')+30])
        
        
        if (std_timestamp > timestamp) and (to_timestamp(date_list[-1][:10]) - timestamp) > 86400 : 
            pass
        if (std_timestamp > timestamp) and (to_timestamp(date_list[-1][:10]) - timestamp) < 86400 : 
            break
        # 게시글 중간에 오래된 게시글이 올라오는 경우가 있어서 이전 게시글과 하루 이상 차이(timestamp 86400)가 나면
        # outlier로 간주하고 pass
        
        
        # 시간
        date_list.append(datetime.fromtimestamp(timestamp).strftime('%Y.%m.%d %H:%M'))
        month_list.append(datetime.fromtimestamp(timestamp).strftime("%m"))
        day_list.append(datetime.fromtimestamp(timestamp).strftime("%d"))

        # 개별 링크 리스트 
        link_list.append("https://www.instagram.com" + post_linkx[i])   
        
        # 좋아요
        try:
            likes = int(contents[: contents.find(' Likes, ')])  # Likes 문자열 앞에 있는 좋아요 개수 추출
        except:
            likes=0  # 좋아요 가 아니라 조회수로 표시되는 경우도 있어 이런 경우는 0으로 표시
        like_list.append(likes)

        # 개별 계정
        if "@" and ")" in contents:
            personal_id = contents[contents.find("@")+1 : contents.find(")")]
        elif "shared a post on Instagram" in contents:
            personal_id = contents[contents.find("@")+1 : contents.find('shared a post on Instagram')]                
        elif "shared a photo on Instagram" in contents:
            personal_id = contents[contents.find("@")+1 : contents.find('shared a photo on Instagram')]                
        elif "@" and ")" not in contents and "on Instagram" in contents:
            personal_id = contents[contents.find("@")+1 : contents.find('on Instagram')]
    
        else :
            personal_id = contents[1: contents.find(' posted on')]
        id_list.append(personal_id)

        '''    
        (@personal_id) on instagram, @persoanlid posted on instagram, personal_id on instgram 등의 형태로 meta 데이터에 표시되기
        때문에 여러 형식별 id 추출 if문 수행
        '''

        # 해시태그
        tag_list.append([])
        for tag_content in post_body.find_all('meta', attrs={'property':"instapp:hashtags"}):
            hashtags = tag_content['content'].rstrip(',')
            tag_list[i].append(hashtags)
        

위 코드로 진행해 본 결과 현재시점부터 std_date로 지정한 날짜까지의 게시물을 가져올 수 있었습니다.

 

Comments