Anaconda Prompt에서 scrapy startproject crawler_test 입력해서 새 프로젝트 생성.
파이참을 켜고 File->Open에서 명령창의 홈 경로에 있는 crawler_test 열기.
items.py 파일을 열고 다음과 같이 입력
import scrapy
class CrawlerTestItem(scrapy.Item): #수집하고자 하는 정보 저장
title = scrapy.Filed()
score = scrapy.Field()
genres = scrapy.Field()
consensus = scrapy.Field()
spiders 폴더에 가서 새 파이썬 파일 생성 rt_spider.py
import scrapy
from crawler_test.items import CrawlerTestItem #crawler_test라는 프로젝트에 있는 items 파일의 클래스 임포트
class RTSpider(scrapy.Spider): #Spider 클래스 상속 받음
name = "RottenTomatoes" #RTSpider 클래스를 식별해주는 스파이더 이름
allowed_domains = ["rottentomatoes.com"]#웹 사이트 도메인 네임
# 여기 있는 웹 페이지와 링크되어 있는 페이지 크롤링
# 서버에 url request하고 응답을 response라는 변수로 받고 parse라는 함수에서 처리
start_urls = ["https://www.rottentomatoes.com/top/bestofrt/?year=2017"]
def parse(self,response):#어떤 부분 스크래핑할 지 명시
명령창에서 얻고자하는 url 입력 scrapy shell "https://www.rottentomatoes.com/top/bestofrt/?year=2017" 입력
개발자 도구를 써서 xpath 얻기, 원하는 부분에 대한 xpath를 얻고 scrapy shell에서 진짜로 내가 원하는 부분이 잘 나오는지 확인해야 한다. 제대로 안나오면 말단의 자식 태그부터 제거하면서 나올 때까지 반복한다.
response.xpath('//*[@id="top_movies_main"]/div/table/tr[1]/td[3]/a/@href/text()')[0].extract() 입력하면
u'/m/lady_bird' 이게 나온다.
본래 url에 위의 sub url을 붙이기 위해 urljoin()을 사용한다.
url = response.xpath('//*[@id="top_movies_main"]/div/table/tr[1]/td[3]/a/@href/text()')[0].extract()
response.urljoin(url)
을 하면 u'https://www.rottentomatoes.com/m/lady_bird' 이게 출력된다.
반복되는 제목, 평점 등의 정보를 뽑아내기 위해 부모 태그를 찾을 필요가 있다.
for tr in response.xpath('//*[@id="top_movies_main"]/div/table/tr'):
href = tr.xpath('./td[3]/a/@href')
url = response.urljoin(href[0].extract())
print(url)
이렇게 입력하면 페이지에 있는 url을 얻을 수 있다. 이 url의 웹페이지를 요청하기 위해 parse함수를 작성한다.
import scrapy
from crawler_test.items import CrawlerTestItem #crawler_test라는 프로젝트에 있는 items 파일의 클래스 임포트
class RTSpider(scrapy.Spider): #Spider 클래스 상속 받음
name = "RottenTomatoes" #RTSpider 클래스를 식별해주는 스파이더 이름
allowed_domains = ["rottentomatoes.com"]#웹 사이트 도메인 네임
# 여기 있는 웹 페이지와 링크되어 있는 페이지 크롤링
# 서버에 url request하고 응답을 response라는 변수로 받고 parse라는 함수에서 처리
start_urls = ["https://www.rottentomatoes.com/top/bestofrt/?year=2017"]
def parse(self,response):#어떤 부분 스크래핑할 지 명시
for tr in response.xpath('//*[@id="top_movies_main"]/div/table/tr'):
href = tr.xpath('./td[3]/a/@href')
url = response.urljoin(href[0].extract())
# url이 함수의 인자로 들어감. 그 url을 어떻게 스크래핑할 지 parse_page_contents 함수에 작성
yield scrapy.Request(url, callback=self.parse_page_contents)def parse_page_contents(self, response):
item = CrawlerTestItem()
item["title"] = response.xpath('//*[@id="heroImageContainer"]/a/h1/text()')[0].extract().strip()
item["score"] = response.xpath('//*[@id="tomato_meter_link"]/span[2]/span/text()')[0].extract()
item["genres"] = response.xpath('//*[@id="mainColumn"]/section[3]/div/div[2]/ul/li[2]/div[2]//a/text()').extract()
consensus_list = response.xpath('//*[@id="all-critics-numbers"]/div/div[2]/p//text()').extract()[3:]
item["consensus"] = ' '.join(consensus_list).strip()
yield item다른 페이지를 읽어들이기 위해 현재 사용하고 있는 명령창의 scrapy shell을 Ctrl+D를 눌러 종료한 뒤
scrapy shell "https://www.rottentomatoes.com/m/lady_bird" 을 입력한다.
이 페이지의 제목을 따오기 위해 크롬 개발자 도구를 이용해 xpath를 얻는다.
scrapy shell에서 response.xpath('//*[@id="heroImageContainer"]/a/h1')를 입력하면 뭔가가 나온다.
response.xpath('//*[@id="heroImageContainer"]/a/h1/text()')를 입력하면 데이터에 문자가 나온다.
response.xpath('//*[@id="heroImageContainer"]/a/h1/text()').extract()를 입력하면 제목이 나오긴 하는데 개행과 공백이 표시된다. 이를 제거하기 위해
response.xpath('//*[@id="heroImageContainer"]/a/h1/text()')[0].extract().strip()를 사용한다. 이는 출력된 리스트의 첫번째 항목을 추출한 뒤 공백을 제거한다는 의미다. [0].extract()와 extract_first()는 같다.
어쨌든 위 문장은 제목을 얻어내는 데 사용된다.
영화의 신선도(참신함의 정도)를 얻기 위해선 아래와 같이 쓴다.
response.xpath('//*[@id="tomato_meter_link"]/span[2]/span/text()')[0].extract()
scrapy shell을 종료하고 cd crawler_test로 이동한다.
scrapy crawl RottenTomatoes 입력한다.
SyntaxError: Non-ASCII character 오류가 난다면
오류가 난 파일의 맨 위에 다음의 주석을 똑같이 입력한다. # -*- coding: utf-8 -*-
출력된 정보를 csv 파일로 저장하고 싶다면
scrapy crawl RottenTomatoes -o rt.csv
수집된 데이터를 item pipline을 통해 정리해서 저장할 수 있다.
pipelines.py 파일에 들어가서
import csv
class CrawlerTestPipeline(object):
def __init__(self): #생성자
# 외부 파일에 쓰기
self.csvwriter = csv.writer(open("rt_movies_new.csv","w"))
# 아래 순서대로 csv에 값을 넣음
self.csvwriter.writerow(["title","score","genres","consensus"])
#spider를 통해 얻은 각 item을 어떻게 처리할 지 명세한다.
def process_item(self, item, spider):
row = []
row.append(item["title"])
row.append(item["score"])
row.append('|'.join(item["genres"])) # x 또는 y 장르라는 표현
row.append(item["consensus"])
self.csvwriter.writerow(row)
return item
위 item pipeline을 사용할 수 있도록 settings.py 파일로 이동해서 주석을 해제한다.
ITEM_PIPELINES = {
'crawler_test.pipelines.CrawlerTestPipeline': 300,
}
item pipeline으로 csv파일을 생성하라고 했기 때문에 -o 명령 없이
scrapy crawl RottenTomatoes를 입력한다.
홈 폴더(C:\Users\xx\crawler_test)로 이동해서 rt_movies_new.csv 파일을 메모장으로 열면 쉼표로 구분된 title score genres consensus에 맞게 레코드가 작성되어 있는 것을 확인할 수 있다.
'Python' 카테고리의 다른 글
Scrapy response.xpath로 데이터 추출하기 (0) | 2018.05.27 |
---|---|
IOError: [Errno 22] invalid mode ('wb') or filename: (0) | 2018.05.27 |
Scrapy의 구조 크롤링 맛보기 (0) | 2018.05.26 |
윈도우에서 scrapy 설치 및 확인 (0) | 2018.05.26 |
우분투에서 크롤링하기 위한 설치 (0) | 2018.05.25 |