본문 바로가기
IT/Scraping

웹 크롤링 모델: 링크를 통한 사이트 크롤링

by Cyber_ 2025. 2. 16.

링크를 통한 사이트 크롤링은 특정 URL 패턴과 일치하는 링크를 모두 따라갈 수 있는 크롤러입니다. 특정 검색 결과나 페이지 목록에 국한되지 않고 사이트 전체에서 데이터를 수집해야 하는 프로젝트에 활용할 수 있으며, 사이트의 페이지가 적절히 구조화되지 않았거나 광범위하게 분산된 경우에 효과적입니다.

 

링크 위치를 확인하는 구조화된 필요하지 않으므로, Website 객체에 검색 페에지에 관한 속성을 둘 필요가 없습니다. 그러나 크롤러가 찾아야 할 링크의 위치에 대한 구체적인 지침이 없으므로 어떤 종류의 페이지를 선택할지 지정하는 규칙이 필요합니다. 여기서는 대상 URL에 대한 정규 표현식인 targetPattern과 불리언 변수 absoluteUrl을 사용할 것입니다.

class Content:
    def __init__(self, url, title, body):
        self.url = url
        self.title = title
        self.body = body

    def print(self)
        print("URL: {}".format(self.url))
        print("Title: {}".format(self.title))
        print("Body:\n{}".format(self.body))

class Website:
    def __init__(self, name, url,targetPattern, absoluteUrl, 
        titleTag, bodyTag):
        self.name = name
        self.url = url
        self.targetPattern = targetPattern
        self.absoluteUrl = absoluteUrl
        self.titleTag = titleTag
        self.bodyTag = bodyTag

 

Crawler 클래스는 각 사이트의 홈 페이지에서 시작하여 내부 링크를 찾고 발견된 각 내무 링크의 내용을 구문 분석하도록 만듭니다.

 

import requests
from bs4 import BeautifulSoup
import re

class Crawler:
    def __init__(self):
        self.site = site
        self.visited = []

    def getPage(self, url):
        try:
            req = requests.get(url)
        except requests.exceptions.RequestException:
            return None
        return BeautifulSoup(req.text, 'html.parser')

    def safeGet(self, pageObj, selector):
        selectedElems = pageObj.select(selector)
        if selectedElems is not None and len(selectedElems) > 0:
            return '\n'.join([elem.get_text() for elem in selectedElems])
        return ''

    def parse(self,url):
        bs = self.getPage(url)
        if bs is not None:
            title = self.safeGet(bs, self.site.titleTag)
            body = self.safeGet(bs, self.site.bodyTag)
            if title != '' and body != '':
                content = Content(url, title, body)
                content.print()

    def crawl(self):
        """
        사이트 홈페이지에서 페이지를 가져옵니다.
        """
        bs = self.getPage(self.site.url)
        targetPages = bs.findAll('a', href=re.compile(self.site.targetPattern))
        for targetPage in targetPages
            tragetPage = targetPage.attrs['href']
            if targetPage not in self.visited:
                self.visited.append(targetPage)
                if not self.site.absoluteUrl:
                    targetPage = '{}{}'.format(self.site.url, targetPage)
                self.parse(targetPage)

reuters = Website('Reuters', 
                  'http://reuters.com',
                   '^(/articles/)',
                   False,
                   'h1',           
                   'div.StandardArticleBOdy_body_1gnLA'


crawler = Crawler(reuters)
crawler.crawl()              

 

이 방법은 방문한 페이지 목록(visited)을 크롤러에 저장하는 데는 문제가 없지만, 크롤러 하나가 웹사이트 리스트를순회할 수는 없고 각 웹사이트마다 새 크롤러를 인스턴스화 해야 합니다.