[R] 요리 사이트 (만개의 레시피) 크롤링 및 정보수집 소스코드

 정보

  • 업무명    : 소프트웨어 개발
  • 작성자    : 박진만
  • 작성일    : 2019-09-07
  • 설   명    : 요리 사이트의 유용한 정보 (ex : 요리이름, 재료, 조리방법, 이미지 주소)를 파싱하여 수집 프로그램
  • 수정이력 :

 

 내용

[특징]

  • R 프로그램의 httr package를 이용하여, 타겟이 되는 사이트에 접근하여 웹 페이지의 html을 가져온 후 이를 가공 및 변환하여, 자료를 수집하는 프로그램 

etc-image-0
그림. 크롤링 대상 사이트 메인 홈페이지

[기능]

  • 타겟이 되는 주소 접근 및 html 불러오기
  • 필요한 자료 가공 및 추출
  • 추출된 정보를 저장 (해당 코드에서는 보안을 위해 생략)

[활용 자료]

  • 대상 홈페이지의 주소 (초기 입력자료)

[자료 처리 방안 및 활용 분석 기법]

  • 없음

[사용법]

  • 대상 홈페이지의 주소 및 i 값 (레시피 번호)를 입력 또는 원하는 범위에서의 loop 문을 통해 레시피 정보를 가져올 수 있다.
  • 중간에 404 에러가 뜨는 경우 루프문을 통과해 다음 레시피 번호로 가게 설정되어 있다.

[사용 OS]

  • Windows 10

[사용 언어]

  • R 3.5.3
 

 소스 코드

#==========================================================================================================================================
# Routine : R Project Web Crawl Program ver 1.2
# crawl site : http://www.10000recipe.com/index.html
# Purpose : To crawl specific information on the website specified above.
# Author : Jin-Man Park (Academy. of KIC Campus)
# Revisions : V1.0 October 31, 2018 First release (Techer. Y.-K. Park)
#==========================================================================================================================================
#================================================================
# 0. library load...
#================================================================
library(rmarkdown)
library(dplyr)
library(dynlm)
library(repr)
library(gstat)
library(stringr)
library(xlsx)
library(XML)
library(httr)
library(curl)
aaa <- paste0("http://www.10000recipe.com/recipe/",i)
sapply(aaa, url.exists)
qqqq<-url(aaa)
i = 6828812 #test
A_table = as.character.Date(data.frame("cook_number" = c("zzz"), "cook_name" = c("zzz"), "cook_explain" = c("zzz"),
"cook_mainimg"= c("zzz"), "cook_people"=c("zzz"), "cook_level" = c("zzz"),
"cook_time" = c("zzz")))
B_table = as.character.Date(data.frame("cook_number" = c("zzz"),"metal"= c("zzz")))
C_table = as.character.Date(data.frame("cook_number" = c("zzz"), "seq_number" = c("zzz"), "seq_text" = c("zzz"),
"seq_img" = c("zzz")))
cookNumber = 0
i
for (i in c(6828809:6899018)) { ## url number :: 6828809 - 6899018
cookNumber = cookNumber + 1
print(i)
print((cookNumber)/(6899018-6828809))
#================================================================
# sequence 1 : url 주소 부여 및 html 소스 가져오기.
#================================================================
url <- paste0("http://www.10000recipe.com/recipe/",i)
xxx <- tryCatch(
{
check <- htmlParse(rawToChar(GET(url)$content)) #html source
},
error = function(e) e
)
if(length(xxx) == 2) next
if(length(xxx) == 1) {
source <- htmlParse(rawToChar(GET(url)$content))
}
#================================================================
# sequence 2 : 요리 이름 및 기본적 정보
# (ex : 이름,간단설명,사람수,조리시간,
# 난이도,타이틀 이미지 주소정보) 가져오기.
#================================================================
cookName <- xpathSApply(source, "//div[@class='view2_summary']/h3", xmlValue)
#cookName #cookname
simpleInfo <- xpathSApply(source, "//div[@class='view2_summary_in']", xmlValue)
simpleInfo <- gsub("[\r\n]","", simpleInfo)
simpleInfo <- gsub("[ ]{2,}|[ ]+$", "", simpleInfo)
#simpleInfo #summary text
inbun <- xpathSApply(source, "//div[@class='view2_summary_info']/span[1]", xmlValue)
time <- xpathSApply(source, "//div[@class='view2_summary_info']/span[2]", xmlValue)
nando <- xpathSApply(source, "//div[@class='view2_summary_info']/span[3]", xmlValue)
TitleImage <- xpathSApply(source, "//div[@class='centeredcrop']/img", xmlAttrs)
TitleImage[2] # image src
if(length(cookName) == 0) {
simpleInfo <- "NAN"
}
if(length(simpleInfo) == 0) {
simpleInfo <- "NAN"
}
if(length(inbun) == 0) {
inbun <- "NAN"
}
if(length(time) == 0) {
time <- "NAN"
}
if(length(nando) == 0) {
nando <- "NAN"
}
A_table = rbind(A_table, c(cookNumber, cookName, simpleInfo,
TitleImage[2], inbun, nando, time))
#================================================================
# sequence 3 : 배열의 형태로 재료 가져오기. (je3)
#================================================================
je <- xpathSApply(source, "//div[@class='ready_ingre3']/ul/li", xmlValue)
je1 <- gsub("[ ]{2,}|[ ]+$", "|", je) #2개 이상의 공백 제거
je2 <- gsub("[\r\n]"," ", je1)
je3 <- gsub("[ ]{2,}|[ ]+$", "", je2) #2개 이상의 공백 제거
je3
length(je3)
#배열 자르기
for (j in c(1:length(je3))) {
# print(je3[j])
B_table = rbind(B_table, c(cookNumber, je3[j]))
} # end j
#================================================================================
# sequence 4 : 배열의 형태로 조리순서 및 조리 이미지(존재유무 불확실)가져오기.
#================================================================================
j = 0
#레시피의 길이를 알 수 없으므로 무한루프에 빠뜨린 후 처리한다.
while(TRUE) {
j = j + 1
dum1 = paste0("//div[@class='view_step_cont media step",j,"']")
cook_seq = xpathSApply(source, dum1, xmlValue)
cook_seq = gsub("[\r\n]","", cook_seq) # get seq
dum2 = paste0("//div[@id='stepimg",j,"']/img")
cook_img = xpathSApply(source, dum2, xmlAttrs) # get img
# 이미지가 없을 경우 임의의 파일 이름 만들기.
if(length(cook_img) == 0) {
cook_img = "noimage.jpg"
}
if(length(cook_seq) == 0) {
break
} else {
# cook_seq, cook_img 쓰기 작업
C_table = rbind(C_table, c(cookNumber,j,cook_seq,cook_img))
}
} # end while
} # end url number
view raw crolling.R hosted with ❤ by GitHub

 

 결과

  • 요리 제목 및 난이도

etc-image-1
그림. 요리 제목 및 난이도에 대한 화면.

 

etc-image-2
그림. 요리 제목 및 난이도에 대한 수집 결과.

 

  • 요리 재료 목록

etc-image-3
그림. 요리 재료에 대한 샘플 화면.

 

etc-image-4
그림. 요리 재료에 대한 수집 결과.

 

  • 조리법 및 이미지

etc-image-5
그림. 조리법 및 이미지에 대한 샘플.

 

etc-image-6
그림. 조리법 및 이미지 주소에 대한 수집결과.

 

 참고문헌

[논문]

  • 없음

[보고서]

  • 없음

[URL]

  • 없음

 

블로그에 대한 궁금하신 점을 문의하시면 자세히 답변드리겠습니다.

E. ​sangho.lee.1990@gmail.com & ​saimang0804@gmail.com