728x90
728x90
Scrapy는 파이썬으로 작성된 오픈 소스 웹 크롤링 프레임워크입니다. 웹 사이트에서 필요한 데이터를 자동으로 추출하여 원하는 형식으로 저장하는 작업을 웹 크롤링이라고 하는데, Scrapy는 이러한 작업을 효율적이고 체계적으로 수행하도록 도와주는 강력한 도구입니다.
Scrapy의 주요 특징
- 빠르고 효율적: 비동기 네트워킹 라이브러리인 Twisted를 기반으로 하여 빠른 속도를 자랑하며, 대규모 웹 사이트를 크롤링하는 데 적합합니다.
- 유연하고 확장성이 좋음: 다양한 데이터 저장 방식, 미들웨어, 아이템 파이프라인 등을 통해 커스터마이징이 가능하여 복잡한 크롤링 작업에도 유용하게 활용할 수 있습니다.
- 간편한 사용: 파이썬 기반으로 개발되어 Python 문법에 익숙한 개발자라면 쉽게 학습하고 사용할 수 있습니다.
- 강력한 기능: XPath, CSS 선택자 등을 이용하여 HTML에서 데이터를 추출하고, 다양한 형식으로 저장할 수 있습니다.
Scrapy를 사용하는 이유
- 복잡한 웹 사이트 크롤링: 자바스크립트로 동적으로 생성되는 콘텐츠, 다양한 레이아웃을 가진 웹 페이지 등 복잡한 구조의 웹 사이트에서도 효과적으로 데이터를 추출할 수 있습니다.
- 대규모 데이터 수집: 많은 양의 데이터를 빠르고 안정적으로 수집해야 할 때 Scrapy는 최적의 선택입니다.
- 데이터 파이프라인 구축: 수집한 데이터를 정제하고 분석하기 위한 파이프라인을 구축할 수 있습니다.
Scrapy의 기본적인 작동 방식
- Spider 생성: 크롤링할 웹 사이트와 추출할 데이터를 정의하는 클래스입니다.
- Request 생성: 크롤링할 URL을 포함하는 Request 객체를 생성합니다.
- Response 처리: Request에 대한 Response를 받아 HTML을 파싱하고 데이터를 추출합니다.
- Item 생성: 추출한 데이터를 저장하기 위한 Item 객체를 생성합니다.
- Item Pipeline: Item을 처리하고 저장하는 파이프라인입니다.
Scrapy의 활용 예시
- 뉴스 기사 수집: 다양한 뉴스 사이트에서 특정 키워드를 포함하는 기사를 수집하여 분석
- 제품 정보 수집: 온라인 쇼핑몰의 제품 정보를 수집하여 가격 비교
- SNS 데이터 분석: SNS에서 특정 해시태그를 가진 게시물을 수집하여 분석
- 웹 사이트 모니터링: 웹 사이트의 변경 사항을 모니터링
728x90
import scrapy
class ExampleSpider(scrapy.Spider):
# 스파이더 이름 설정
name = 'example_spider'
# 크롤링 허용 도메인 설정 (example.com 에서만 크롤링하도록 설정)
allowed_domains = ['example.com']
# 시작 URL 설정 (크롤링을 시작하는 첫 페이지)
start_urls = ['https://example.com']
def parse(self, response):
# 웹 페이지의 타이틀 추출
title = response.css('title::text').get()
print(f"** Main Page Title: {title} **")
# 모든 a 태그의 href 속성값 추출 (링크 목록)
hrefs = response.css('a::attr(href)').getall()
# 추출한 링크 목록을 반복하며 follow_link 함수 호출
for href in hrefs:
yield scrapy.Request(href, callback=self.parse_details)
def parse_details(self, response):
# 상세 페이지의 모든 p 태그 안의 텍스트 추출
content = response.css('p::text').getall()
content = "\n".join(content) # 리스트를 한 줄 문자열로 변환
print(f"\n** Detail Page Content: \n{content} **")
# 추출한 내용을 사전(dict) 형태로 yield
yield {'content': content}
설명
- import scrapy: scrapy 라이브러리를 불러옵니다.
- class ExampleSpider(scrapy.Spider): ExampleSpider라는 이름의 스파이더 클래스를 정의합니다.
- name = 'example_spider': 스파이더의 이름을 설정합니다.
- allowed_domains = ['example.com']: 크롤링을 허용하는 도메인을 설정합니다. 이 코드에서는 'example.com' 에서만 크롤링하도록 설정되어 있습니다.
- start_urls = ['https://example.com']: 크롤링을 시작하는 첫 페이지 URL을 설정합니다.
- def parse(self, response):: 웹 페이지를 다운로드 받으면 실행되는 메서드입니다.
- title = response.css('title::text').get(): response 객체에서 title 태그의 텍스트를 추출합니다.
- print(f" Main Page Title: {title} "): 추출한 타이틀을 출력합니다.
- hrefs = response.css('a::attr(href)').getall(): response 객체에서 모든 a 태그의 href 속성값을 리스트 형태로 추출합니다.
- for href in hrefs: hrefs 리스트를 반복하며 각 링크에 대해 다음을 수행합니다.
- yield scrapy.Request(href, callback=self.parse_details): 추출한 링크(href)에 대해 새로운 Request 객체를 생성합니다. callback 매개변수에는 parse_details 메서드를 지정합니다.
- def parse_details(self, response):: 상세 페이지를 다운로드 받으면 실행되는 메서드입니다.
- content = response.css('p::text').getall(): response 객체에서 모든 p 태그 안의 텍스트를 리스트 형태로 추출합니다.
- content = "\n".join(content): 리스트에 있는 문자열들을 줄 바꿈 문자(\n)로 연결하여 하나의 문자열로 만듭니다.
- print(f"\n Detail Page Content: \n{content} "): 추출한 내용을 출력합니다.
- yield {'content': content}: 추출한 내용을 'content' 키값을 가지는 사전(dict) 형태로 yield합니다.
728x90
예시 HTML
<!DOCTYPE html>
<html>
<head>
<title>Example Website</title>
</head>
<body>
<h1>This is the main page</h1>
<p>This is some content on the main page.</p>
<a href="detail_page1.html">Go to detail page 1</a>
<a href="detail_page2.html">Go to detail page 2</a>
</body>
</html>
실행 결과
Running scrapy crawl example_spider
** Main Page Title: Example Website **
** Detail Page Content:
다른예
import scrapy
class NewsSpider(scrapy.Spider):
# 스파이더 이름 설정
name = 'news_spider'
# 크롤링 허용 도메인 설정
allowed_domains = ['news.example.com']
# 시작 URL 설정
start_urls = ['https://news.example.com/']
def parse(self, response):
# 뉴스 기사 목록 추출 (h2 태그 안에 a 태그가 있는 구조)
news_links = response.css('h2 a::attr(href)')
# 추출한 링크 목록을 반복하며 상세 페이지 크롤링
for news_link in news_links:
yield scrapy.Request(news_link.get(), callback=self.parse_news)
def parse_news(self, response):
# 뉴스 제목 추출
title = response.css('h1::text').get()
# 뉴스 본문 p 태그 안의 텍스트 추출 (리스트 형태)
content = response.css('p::text').getall()
# 리스트를 하나의 문자열로 변환
content = "\n".join(content)
# 뉴스 작성 시간 추출 (span 태그 클래스명이 "date")
date = response.css('span.date::text').get()
# 추출한 데이터 사전(dict) 형태로 yield
yield {
'title': title,
'content': content,
'date': date,
}
# 예시 HTML (상세 페이지 포함)
html_content = """
<!DOCTYPE html>
<html>
<head>
<title>News Website</title>
</head>
<body>
<h1>This is the main page</h1>
<p>This is some content on the main page with links to news articles.</p>
<a href="article_1.html">News Article 1</a>
<a href="article_2.html">News Article 2</a>
<article>
<h1>This is News Article 1</h1>
<p>This is the content of the first news article.</p>
<p>This is another paragraph of content.</p>
<span class="date">2024-12-26</span>
</article>
</body>
</html>
"""
# 실행 결과 (콘솔 출력)
# {'title': 'This is News Article 1', 'content': 'This is the content of the first news article.\nThis is another paragraph of content.', 'date': '2024-12-26'}
# ... (다른 뉴스 기사 결과도 출력)
설명
- import scrapy: scrapy 라이브러리를 불러옵니다.
- class NewsSpider(scrapy.Spider): NewsSpider라는 이름의 스파이더 클래스를 정의합니다.
- name = 'news_spider': 스파이더의 이름을 설정합니다.
- allowed_domains = ['news.example.com']: 크롤링을 허용하는 도메인을 설정합니다.
- start_urls = ['https://news.example.com/']: 크롤링을 시작하는 첫 페이지 URL을 설정합니다.
- def parse(self, response):: 웹 페이지를 다운로드 받으면 실행되는 메서드입니다.
- news_links = response.css('h2 a::attr(href)'): h2 태그 안에 a 태그가 있는 모든 링크의 href 속성값을 추출합니다.
- for news_link in news_links: 추출한 링크 목록을 반복하며 각 뉴스 기사 상세 페이지로 이동합니다.
- yield scrapy.Request(news_link.get(), callback=self.parse_news): 추출한 링크에 대해 새로운 Request 객체를 생성합니다. callback 매개변수에는 parse_news 메서드를 지정합니다.
- def parse_news(self, response):: 상세 페이지를 다운로드 받으면 실행되는 메서드입니다.
- title = response.css('h1::text').get(): 뉴스 제목을 h1 태그의 텍스트 내용으로 추출합니다.
- content = response.css('p::text').getall(): 뉴스 본문의 모든 p 태그 안
728x90
728x90
'Python을 배워보자' 카테고리의 다른 글
JupyterLab 초기 진입 경로 지정하기: 효율적인 작업 환경 구축 가이드 (0) | 2024.12.25 |
---|---|
Python의 yield 키워드를 활용한 효율적인 데이터 처리 (0) | 2024.12.25 |
IPython Notebook에서 ipywidgets를 활용한 인터랙티브 GUI 구현 가이드 (0) | 2024.12.25 |
Python과 Electron을 활용한 데스크톱 애플리케이션 개발: 웹 기술의 확장과 데스크톱 환경의 만남 (1) | 2024.12.14 |
Python cx_Oracle 설치: 오라클 데이터베이스와의 연결을 위한 상세 가이드 (0) | 2024.11.27 |