구동환경
1) python 3.6
2) Miniconda3
3) jupyter notebook
4) scrapy
위 그림 설명
1) cmd로 들어가서 activate py27 입력
2) scrapy startproject movie_crawler 입력 (path가 된 폴더에 movie_crawler 폴더가 생성, scrapy 준비 완료)
url 화면.
https://www.rottentomatoes.com/top/bestofrt/?year=2017 <- 스크랩이 될 url
2017년에 개봉한 영화중 순위가 높은 순서대로 스크랩 후 액셀 저장.
작업 순서
1) rt_crawler 폴더안에 rt_spider라는 .py 파일을 만들어서 아래와 같이 입력한다.
#-*- coding: utf-8 -*-
#activate py27 -> cd rt_crawler -> scrapy crawl RottenTomatoes
#1.item.py에서 필드 설정
#2.rt_spider.py에서 코드 입력
#3.pipeline.py에서 코드 입력
#4.setting.py에서 코드 설정
#scrapy 라이브러리
import scrapy
from rt_crawler.items import RTItem
class RTSpider(scrapy.Spider):
name = "RottenTomatoes" # scrapy crawl 실행 이름
allowed_domains = ["rottentomatoes.com"] # 허용된 도메인
start_urls = ["https://www.rottentomatoes.com/top/bestofrt/?year=2017"] # 정보 검색하려는 페이지
#xpath값 삽입.
def parse(self, response):
for tr in response.xpath('//*[@id="top_movies_main"]/div/table/tr'): # 정보 검색하려는 페이지의 영화 제목
href = tr.xpath('./td[3]/a/@href') # href는 속성값
url = response.urljoin(href[0].extract()) # 허용된 도메인에 서브 URL붙이기
yield scrapy.Request(url, callback=self.parse_page_contents) # 서브 URL 붙인 최종 URL 반출, 최종URL에서 불러들일 정보 반출
def parse_page_contents(self, response): #parse_page_contents 함수 작성
item = RTItem()
item["title"] = response.xpath('//*[@id="movie-title"]/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/ul/li[2]/div[2]/a[1]/text()')[0].extract().strip() #장르 스크랩
item["runtime"] = response.xpath('//*[@id="mainColumn"]/section[3]/div/div/ul/li[8]/div[2]/time/text()')[0].extract().strip() #런타임 스크랩
consensus_list = response.xpath('//*[@id="all-critics-numbers"]/div/div[2]/p//text()').extract()[2:] #설명 스크랩
item["consensus"] = ' '.join(consensus_list).strip()
yield item #아이템 반출
2) rt_crawler 폴더에 만들어져있는 item.py에 들어가서 아래와 같이 입력한다.
import scrapy
class RTItem(scrapy.Item) :
title = scrapy.Field()
score = scrapy.Field()
genres = scrapy.Field()
runtime = scrapy.Field()
consensus = scrapy.Field()
3) rt_crawler 폴더에 만들어져있는 pipeline.py에 들어가서 아래와 같이 입력한다.
import csv
class RTPipeline(object):
def __init__(self):
self.csvwriter = csv.writer(open("rt_movies_new.csv", "w"))
self.csvwriter.writerow(["title", "score", "genres", "runtime", "consensus"])
def process_item(self, item, spider):
row = []
row.append(item["title"])
row.append(item["score"])
row.append('|'.join(item["genres"]))
row.append(item["runtime"])
row.append(item["consensus"])
self.csvwriter.writerow(row)
return item
4) rt_crawler 폴더에 만들어져있는 setting.py에 들어가서 코드를 아래와 같이 수정한다.
ITEM_PIPELINES = {
'rt_crawler.pipelines.RTPipeline': 400,
}
5) cmd창에서 scrapy crawl RottenTomatoes 입력.
6) 엑셀에 스크랩하려는 정보를 저장시킨다.
url을 반복문으로 반출하기
<rt_crawler.py>
def parse(self, response):
for tr in response.xpath('//*[@id="top_movies_main"]/div/table/tr'): # 정보 검색하려는 페이지의 영화 제목
href = tr.xpath('./td[3]/a/@href') # href는 속성값
url = response.urljoin(href[0].extract()) # 허용된 도메인에 서브 URL붙이기
yield scrapy.Request(url, callback=self.parse_page_contents) # 서브 URL 붙인 최종 URL 반출, 최종URL에서 불러들일 정보 반출
activate py27 -> scrapy startproject rt_crawler -> scrapy shell ('url1')의 환경에서 (url1 : 스크랩할 페이지)
reponse.xpath('xpath')을 실행시킨다.
<괄호 안에 들어갈 xpath 예시>
개발자도구 (컨트롤+쉬프트+i) -> 엘리먼트 선택(컨트롤+쉬프트+c)
영화 Get out에 마우스 커서를 갖다대면 사진의 오른쪽과 같이 (a herf ~) 파란색 박스가 뜨게 된다.
해당 박스에 오른쪽 마우스를 누르면 Copy Xpath가 뜨게 된다.
클릭하여 실행창에 붙여넣으면 //*[@id="top_movies_main"]/div/table/tbody/tr[1]/td[3]/a 와 같은 문장이 나오게 된다.
이 문장을 위에 설명한 환경에서 reponse.xpath('//*[@id="top_movies_main"]/div/table/tbody/tr[1]/td[3]/a') 이런 식으로 넣게되면
copy xpath에 해당하는 element가 무엇인지 출력하게 된다.
위 그림은 //*[@id="top_movies_main"]/div/table/tbody/tr[1]/td[3]/a 를 조금씩 수정하면서 출력값을 얻어낸 화면이다.
최종적으로 맨밑에줄에
response.xpath('//*[@id="top_movies_main"]/div/table/tr[1]/td[3]/a/@href')[0].extract 을 실행하면 get out이라는 엘리먼트가 출력된다.
(href는 엘리먼트의 속성값)
get out이외의 다른 엘리먼트의 xpath를 복사하면 tr[1], tr[2], tr[3],.. 이런식으로 1위 ~ n위까지 path가 생성된다.
따라서 아래의 코드를 입력하여 반복적으로 url을 스크랩해온다.
for tr in response.xpath('//*[@id="top_movies_main"]/div/table/tr'): # 정보 검색하려는 페이지의 영화 제목
href = tr.xpath('./td[3]/a/@href') # href는 속성값
url = response.urljoin(href[0].extract()) # 허용된 도메인에 서브 URL붙이기
yield scrapy.Request(url, callback=self.parse_page_contents) # 서브 URL 붙인 최종 URL 반출, 최종URL에서 불러들일 정보 반출
정리해서 위의 코드를 해석하면,
xpath를 불러옴 -> href로 속성값을 따옴 -> 허용된 도메인에 href가 포함된 url 붙이기 -> 최종 url 반출.
contents를 xpath로 불어들이기
평점, 줄거리에 대한 엘리먼트값 확인
def parse_page_contents(self, response): #parse_page_contents 함수 작성
item = RTItem()
item["title"] = response.xpath('//*[@id="movie-title"]/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/ul/li[2]/div[2]/a[1]/text()')[0].extract().strip() #장르 스크랩
item["runtime"] = response.xpath('//*[@id="mainColumn"]/section[3]/div/div/ul/li[8]/div[2]/time/text()')[0].extract().strip() #런타임 스크랩
consensus_list = response.xpath('//*[@id="all-critics-numbers"]/div/div[2]/p//text()').extract()[2:] #설명 스크랩
item["consensus"] = ' '.join(consensus_list).strip()
yield item #아이템 반출
위 코드는 url에서 했던 내용과 일치한다.
각 아이템의 제목을 명시하고 response.xpath('')로 엘리먼트를 불러들인다.
+ xpath복사 후 /text() 추가 : 글자만 스크랩한다.
+ .strip()을 추가하여 해당 내용 외의 불필요한 소스들 제거
pipeline.py을 이용하여 엑셀에 저장하기
import csv
class RTPipeline(object):
def __init__(self):
self.csvwriter = csv.writer(open("rt_movies_new.csv", "w"))
self.csvwriter.writerow(["title", "score", "genres", "runtime", "consensus"])
def process_item(self, item, spider):
row = []
row.append(item["title"])
row.append(item["score"])
row.append(item["genres"])
row.append(item["runtime"])
row.append(item["consensus"])
self.csvwriter.writerow(row)
return item
item.py을 이용하여 변수 설정하기
import scrapy
class RTItem(scrapy.Item) :
title = scrapy.Field()
score = scrapy.Field()
genres = scrapy.Field()
runtime = scrapy.Field()
consensus = scrapy.Field()
이 상태에서 실행창에 scrapy crawl RottenTomatoes를 입력하면 엑셀에 스크랩한 정보가 저장된다.
'코딩이것저것' 카테고리의 다른 글
키움증권 API를 이용한 자동매매 (0) | 2018.04.18 |
---|---|
동적 웹 페이지에서 데이터 추출하고 수집하기 (0) | 2017.09.02 |
CNN_deep CNN mnist (0) | 2017.08.07 |
CNN_drop out, ensemble (0) | 2017.08.06 |
CNN_weight initialization (0) | 2017.08.06 |