web-scraping-3-638.jpg

본 재고검색 사이트의 가장 주축기능은 역시 크롤링이다. 각 서점 플랫폼에서 제공하는 재고정보 데이터를 가져와서(Crawling) 알맞게 재가공하여 이용자에게 보여줘야한다. 크롤링 기능을 구현하기위해선

첫번째로 데이터를 제공하는 사이트에 접속하는 단계,

두번째로 사이트에서 데이터를 받아오는 단계,

세번째로 가져온 데이터에서 원하는 정보만 가져오는 단계 크게 3가지로 구분할 수 있겠다

첫번째 및 두번째 단계 : 사이트 접속

파이썬에서 웹에 접속, 즉 HTTP 통신을 행하기 위해서 여러가지 방법이 존재하지만 우리는 Requests 모듈을 이용하기로했다. (개인적으로 많이 사용해본 Requests가 Urllib보다 편했다)

Requests모듈에는 원하는 사이트에 대한 접속 및 해당 사이트가 제공하는 Html문서의 원문을 문자열로 받아와주는 기능을 가지고 있다.

def getStock(isbn):
    url = 'http://www.kyobobook.co.kr/prom/2013/general/StoreStockTable.jsp?barcode=' + isbn + '&ejkgb=KOR'
    headers = {
        'referer' : 'http://www.naver.com',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'
    }
    res = requests.get(url, headers=headers)

위 코드와 같이 접속하고자 하는 url에(교보문고 주소) 추가적으로 헤더정보를 덧붙여서 HTTP requests 요청을 보낼 수 있다.

requests.get() 메서드로 해당 사이트와의 통신객체를 생성(res)한 뒤 , res.text()메서드로 해당 Html 문서의 내용을 문자열로 받아 올 수 있다

세번째 단계 : 데이터 받아오기(parsing)

원문 그대로의 Html문서의 데이터에서 우리는 원하는 특정 데이터의 내용만을 콕 집어내야한다. 그렇게하기위한 가장 원시적인 방법으로는 정규식을 이용하여 일일이 키워드를 매칭해서 데이터를 따오는 방법이 있다.

이전에 작업했던 축구관련 크롤링 웹사이트에서는 정규식을 이용한 파싱을 일부 사용해봤는데, 해당 방식의 단점은 일단 어렵다. 정규식으로 파싱로직을 짜는것이 쉽지 않기때문에, 코드도 무척 지저분해지고 특히나 크롤링할려는 사이트의 Html 정보가 업데이트되면 너무 쉽게 기능성을 잃게 된다.즉 기능성을 쉽게 잃지않도록 적절한 정규식 파싱 코드를 짜는게 너무 어렵다.

따라서 우리는 BeautifulSoup이라는 파싱을 도와주는 파이썬의 모듈을 이용했다. BeautifulSoup은 HTML의 Dom트리 구조를 이용하여 데이터를 파싱한다. Dom트리에서 자신이 가져오고자하는 데이터가 존재하고 있는 태그 위치 혹은 태그 ID를 입력하면 해당 태그내의 정보만 가져온다.

Dom.png

해당 트리도의 각 Node는 태그를 의미하며, 해당 태그의 안에는 특정 데이터들이 위치하고 있다. BeautifulSoup은 트리의 태그를 따라가 원하는 데이터를 가져와준다.

BeautifulSoup 사용! 조금 더 자세히

def book_info(soup):
      url = 'https://book.naver.com/search/search.nhn?sm=sta_hty.book&sug=&where=nexearch&query=' + txt
    req = requests.get(url)
    soup = BS(req.text, 'html.parser')
    info = {}
    con = soup.find('div', {'class':'book_info'})
    inner = soup.select('.book_info_inner > div')[1]
    info['title'] = con.select_one('h2 > a').text
    info['img'] = con.select_one('.thumb_type img')['src']
    info['auth'] = inner.select('a')[0].text
    info['pub'] = inner.select('a')[1].text
    bID = soup.select_one('.book_info_inner')

return info

사이트 제작초기의 코드중 BeautifulSoup에 관한 내용의 코드 일부문 이다.

requests.get(url)을 통하여 원하는 사이트와 통신을 시작하고, text 메서드로 해당 사이트의 HTML 문서를 문자열로 가져온다.

이후 가져온 문자열을 바탕으로 BeautifulSoup 파싱객체를 생성한다.(Var soup)
이 객체(Var soup)를 이용해서 DOM트리의 태그를 따라가며 데이터를 가져올 수 있다.

태그를 따라가는 기능의 구현은 BeautifulSoup 객체의 find와 select 메서드를 이용하여 사용한다.

두 메서드는 사실 동일한 기능을 수행한다. 단지 select 메서드는 태그를 찾아가는데 있어서 css 셀럭터문을 이용할 수 있다는 차이뿐이다.(문법의 차이)

con = soup.find('div', {'class':'book_info'})

book_info 클래스 속성을 가지고 있는 div 태그중 가장 첫번째로 발견되는 정보를 가져온다.
(해당되는 정보를 모두 가져오고 싶다면 findall을 이용한다)

**bs의 select 사용법**
soup.select('태그')
soup.select('.클래스명') 혹은 ('태그.클래스명')
soup.select('#아이디명') 혹은 ('태그#아이디명')
soup.select('태그 > 자식태그')
soup.select('태그 자손태그')

(select는 해당되는 정보를 모두 가져오는데 가장 첫번째 발견되는 정보 하나만 가져오고 싶다면 select_one을 이용)

BeautifulSoup 사용법에 대한 더 디테일한 추가적인 정보는 따로 BeautifulSoup 문서란에서 기술 하겠음 --> 해당 링크(https://velog.io/@dlshl92)