파이썬 bs4와 requests라이브러리 동적페이지 크롤링 질문 드립니다!

조회수 1189회

파이썬 공부한지 한달된 초보입니다. requests와 BeautifulSoup 라이브러리를 사용하여 쿠팡, 위메프, 티몬 사이트에서 상품을 최저가순으로 검색후 상품명과 상품가격을 딕셔너리 형태로 만드는 코드를 과제를 하고있는데 쿠팡과 위메프는 쉽게 끝냇으나 티몬은 동적인페이지라 쿠팡과 위메프 코드처럼 사용하니 안되더라구요; 검색해보니 selenium이라는 프레임워크를 사용하면 된다고 나와 있으나 과외해주시는분이 selenium말고 뷰티플수프와 리퀘스트만으로 해결해보라고 하시는데 방법을 모르겠습니다.

f = open('tmon.html', 'wb')
        f.write(req.content) 
        f.close() 

위의 코드로 저장받아 확인해보니 검색한 상품목록관련 코드가 없고 서비스 이용이 원할하지 않아 현재 검색결과를 정상적으로 가져오지 못합니다.라는 에러메세지 코드가 있는데 bs4와 requests만으로 동적페이지를 어떻게 크롤링해야하나요?? 제가 생각해본 방법은 리퀘스트를 받을때 바로 받는것이 아닌 요청 후 약간의 텀(상품목록이 로딩되는 시간)을 두고 받아온다. 라고 생각을 해서 아래의 코드처럼 리퀘스트 겟 요청시 timeout=5을 추가로 주었음에도 결과값이 다를바가 없네요. 어떤방식으로 접근을 해야할까요??

 req = requests.get("http://search.tmon.co.kr/search/?keyword=%s&thr=ts#저가순" % (keyword), headers=self.headers, timeout=5)

아래의 코드가 제가 작성한 코드전체입니다.

import requests
from bs4 import BeautifulSoup

class tmon(object):
    headers = {}    #검색함수에서만 사용되는것이 아닌 클래스내에 존재하는 모든 함수에서도 사용해야 하므로 전역변수로 사용하고, 사용자가 크롬이아닌 다른 브라우저를 사용 할 수 있기때문에 값을 비워두고 변수를 생성한다.

    def __init__(self, headers={}): #headers를 입력받을수 있게 파라미터 값으로 설정한다.
        if not headers:
            self.headers={'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36'}
        else:
            self.headers = headers
        #클래스를 생성할때 headers의 값을 입력하지 않으면 기본값으로 설정하고 headers의 값을 입력할 경우 해당 값을 headers에 넣음

    def search(self, keyword): #함수를 호출 할때 키워드를 입력받기 때문에 파라미터로 넣는다.
        product_list = [] #결과값을 넣기 위해 빈 배열 변수를 생성한다.
        req = requests.get("http://search.tmon.co.kr/search/?keyword=%s&thr=ts#저가순" % (keyword), headers=self.headers) #티몬검색창을 리퀘스트 겟방식으로 받아오고 headers에 존재하는 유저에이전트 값을 바꿔 담는다.

        content = req.content #겟방식으로 가져온 값의 콘텐츠만을 변수에 담는다.

        soup = BeautifulSoup(content, 'lxml') #콘텐츠를 뷰티플수프로 lxml형태로 변환하여 변수에 담는다.

        product = soup.find("ul", {'class' : 'list'}).find_all("li") #검색된 상품의 이름과 가격을 담고있는 태그를 찾는다.

        for i in product: #li태그안에 가격과 상품이름이 다른 태그로 저장되어 있으므로 for문으로 값을 찾는다.
            proName= i.find("strong", {'class' : 'tx'}).text #상품이름의 text만을 변수에 담는다.
            proPrice = i.find("i", {'class' : 'num'}).text #상품가격의 text만을 변수에 담는다.
            proPrice = int(proPrice.replace(",","")) #가격이 스트링 형태로 되어 있기 때문에 ,를 리플레이스로 제거하고 정수형으로 변환하여 담는다.

            result = {'proName' : proName, 'proPrice' : proPrice} #변수에 담은 상품명과 가격을 딕셔너리형태로 하나의 변수에 담는다.
            product_list.append(result) #위에서 만든 결과값을 넣는 빈배열 변수에 딕셔너리형태의 값을 넣는다.

        return product_list #상품정보를 담은 리스트를 리턴한다.
if __name__ == "__main__":
    test = tmon()
    print(test.search("액션캠"))

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)