본문 바로가기

Python/crawling-instagram

Python 인스타그램 크롤링-크롤링관련 소스(1)

반응형

 

안녕하세요. 인스타그램 크롤링 프로젝트 중 크롤링과 관련된 소스에 대한 설명입니다. 전체 구조 중 CraCrawlingInstagramMng.py에 대해 설명하겠습니다.

 

 

인스타그램 크롤링 클래스는 크롤링 과정에 필요한 기능을 제공합니다. 이에 필요한 로그인, 검색, 게시글 정보, 이미지 정보, 인스타그램 URL 게시글 정보 수집과 같은 메소드를 구현하였습니다. 전체적인 로직은 하단 이미지와 같습니다.

 

로그인

로그인은 필수 조건은 아닙니다. 하지만 게시자가 팔로워에게만 공개되는 게시글의 정보를 크롤링하기 위해서는 로그인이 필요합니다. 그리고 웹페이지 로드를 위해 로그인하기 버튼 , 로그인 버튼 클릭 후 3초간의 대기 시간을 가집니다.

    def LoginInstagram(self, strId, strPassword) :
        self.driver.get('https://www.instagram.com/accounts/login/?source=auth_switcher')
        time.sleep(3) #웹 페이지 로드를 보장하기 위해 3초 쉬기
        id_input = self.driver.find_elements_by_css_selector('#react-root > section > main > div > article > div > div > div > form > div >  div > div > label > input')[0]
        id_input.send_keys(strId)
        password_input = self.driver.find_elements_by_css_selector('#react-root > section > main > div > article > div > div > div > form > div >div > div > label > input')[1]
        password_input.send_keys(strPassword)
        password_input.submit()
        time.sleep(3)

 

사용자 및 키워드 검색

인스타그램의 검색 종류는 두 가지로 나뉩니다. 좌측과 같은 이미지 검색, 우측같은 해시태그 검색으로 나뉩니다. 이 두가지 메소드를 나눠서 구현한 이유는 하단 ulr의 차이가 있기 때문입니다.

인물 : www.instagram.com/인물계정

해시태그 : http://www.inwww.instagram.com/explore/tags/해시태그

    def searchKeyword(self, strkeyword):
        url = "https://www.instagram.com/explore/tags/{}/".format(strkeyword)
        self.driver.get(url)
        time.sleep(3)
    
    
    def searchUserId(self, strUserId):
        url = "https://www.instagram.com/{0}/".format(strUserId)
        self.driver.get(url)
        time.sleep(3)

 

반응형

전체 URL 얻기

검색된 게시글을 크롤링하여 URL만 추출하여 저장하는 과정입니다. 아래 그림과 같이 현재 보이는 게시글의 모든 정보를 얻어옵니다. 그리고 스크롤을 최하단으로 내려간 후 다시 게시글의 ULR을 저장해주는 것을 반복합니다.

그리고 두 가지 조건인 경우 모든 데이터 수집을 완료한 것으로 판단합니다.

1. 게시물 개수와 ULR의 개수가 동일해지는 경우

2. 10회 이상 추가되는 ULR이 없는 경우 

 

 여기서 기존 설계로는 전체 URL얻기와 게시글 얻기 두 가지를 한번에 하려고 했으나 검색 개수가 많으지는 경우 한계를 보여 이를 보완하기 위해 전체 URL을 읽는 로직을 별도로 구현하였습니다. 추후 기회가 된다면 포스팅하겠습니다.

 

 

    def ReadAllLink(self, nContentCnt = 0) :
        SCROLL_PAUSE_TIME = 1.0
        reallink = []

        pageString = self.driver.page_source
        bsObj = BeautifulSoup(pageString, 'lxml')

        nContentSize = 0
        listcontentCnt = bsObj.select('span.g47SY')
        if len(listcontentCnt) != 0 :
            strContentSize = str(bsObj.select('span.g47SY')[0].text)
            nContentSize = int(strContentSize.replace(',', ''))

        #더이상 새로운것들이 안 읽어지면 끝내준다.
        nCountCheck = 0
        nPrevlinkCnt = 0
        while True :

            if nContentCnt == len(reallink) and nContentCnt != 0:
                break

            pageString = self.driver.page_source
            bsObj = BeautifulSoup(pageString, 'lxml')
        
            for link1 in bsObj.find_all(name='div', attrs={"class":"Nnq7C weEfm"}):
                SelData = link1.select('a')
                for i in range(len(SelData)):
                    title = SelData[i]
                    real = title.attrs['href']
                    reallink.append(real)

            last_height = self.driver.execute_script('return document.body.scrollHeight')
            self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            time.sleep(SCROLL_PAUSE_TIME)
            new_height = self.driver.execute_script("return document.body.scrollHeight")

            #여기 들어오는게 리프래시가 잘 안되는경우..??일것임..
            if new_height == last_height:
                # 리프레시가 잘 안되는 경우가 있어서 처음으로 한번 갔다가 오면 잘되는듯하다!!
                self.driver.execute_script("window.scrollTo(0, 100);")
                time.sleep(SCROLL_PAUSE_TIME)
                new_height = self.driver.execute_script("return document.body.scrollHeight")

                last_height = new_height
                time.sleep(5)

            ##링크데이터 중복을 제거해준다!! -> 크롤링하며 얻어오는 과정에서 중복으로 입력되는 것!(스크롤내리면서 똑같은게 보일수 잇으니)
            setlink = set(reallink)
            reallink = list(setlink)


            if nContentSize == len(reallink) :
                break

            #얻은 개수와 똑같아 지면 브레이크! -> 너무 많은 경우는 개수가 없다..
            if nPrevlinkCnt == len(reallink) :
                nCountCheck += 1
            else : 
                nCountCheck = 0

            if nCountCheck > 10 :
                break

            #얻은 개수와 똑같아 지면 브레이크!
            nPrevlinkCnt = len(reallink)

            print("Current Count =" + str(len(reallink)) )
           
        print("AllSize = " + str(nContentSize) + "\tFinishCount =" + str(len(reallink)) )
        
        return reallink;

특이 사항으로는 인스타그램 크롤링 과정에서 스크롤을 최하단으로 내려도 웹로딩이 잘 안되는 경우가 발생하였는데 저 같은 경우에는 스크롤을 최상단으로 올린 후 하단으로 내리면 로딩이 더 빠른 것을 확인하였스니 참고하세요

 

 

 

게시글이 길어져서 다음 게시글 얻기, URL검색, 이미지 얻기는 다음 포스팅에 이어서 하겠습니다....

 

 

반응형