본문 바로가기
컴퓨터

XBMC 스크래퍼 만들기

by Moon Madness 2015. 4. 2.

처음시작하기

스크래퍼를 만드는데에는 XML과 Regular Expression에 익숙해야 합니다.

아마 perl/python같은 스크립트 언어나 적어도 vi 를 쓰시는 분들은 시작하는데 큰 어려움은 없을 겁니다.

스크래퍼의 XML 구조는 XBMC Wiki 에 설명되어 있습니다. 그런데 오래 되기도 했고, 너무 간략한 설명이 되나서 이것만 보고는 절대 시작할 수 없습니다.

차라리 HOW-TO write Media Info Scrapers 문서가 예를 들어서 설명하기 때문에 꼭 읽어야할 문서입니다.


사실 그래도 막상 만들려면 엄청 귀찮습니다. 특히 <>" 등과 같은 특수문자들이 난무하면 암만 regular expression에 자신있어도 눈이 빠집니다.

그럴때를 위해서 ScraperXML Editor 가 있습니다.

아직 버그가 있어서 에디터 상에서 스크래터를 실행해볼 수는 없지만 여러 장점이 많습니다.

- Template 생성
- 특수문자 변환
- XML 문법 오류 검사
- Predefined Function 경우 argument가 어떤 것인지 설명
- 풍선 도움말 (처음 두 문서에 없는 설정들이 뭔지 추측할 수 있습니다)
- Regular Expression을 선택해서 실행해보기


스크래퍼 기본

스크래퍼는 기본적으로 다음 함수들을 가진다.


함수이름

Return 

설명 

GetSettings 
설정변수에 대한 정의

NfoUrl

 <url>

 NFO 파일이 비디오파일과 있을 때 NFO안에서 URL을 끄집어냄 

CreateSearchUrl

 <url>

 파일이름으로 영화를 검색할 때 쓸 URL을 만듬

GetSearchResults

 <results>

 검색결과 페이지에서 영화정보들을 parsing하고 이를 list로 만듬. 사용자는 이들 중 하나를 선택하게 됨.

GetDetails

 <details>

 영화정보 페이지에서 필요한 정보들을 추출함. 영화이름/감독,배우이름/줄거리/포스터 등등

GetEpisodeList

 <episodeguide>

 (TV쇼에서만 씀) Episode 페이지에서 이름/회차 등의 정보와 각 Episode 정보를 가지고 있는 URL을 추출

GetEpisodeDetails

 <details>

 (TV쇼에서만 씀) Episode 정보 페이지에서 줄거리, 배우등의 자세한 정보를 추출


각 함수가 불리는 과정을 살펴보면

    1. 파일과 같은 위치에 .nfo 파일이 있다면 NfoUrl 을 호출. GetDetails로 건너뜀.

    2. NFO가 없다면 CreateSearchUrl에서 파일이름을 가지고 어떻게 검색할지를 정함.

    3. GetSearchResults에서 검색결과 페이지에서 검색된 이름, 연도, 영화정보 URL을 추출한다.

    4. 선택된 영화정보 페이지를 가지고 GetDetails 함수가 불림. 만약 보다 자세한 정보를 위해 다른 페이지를 봐야한다면 커스텀함수를 작성하고 호출해야 한다.

    5. (TV경우) 에피소드가 들어있는 주소들을 <episodeguide> 에 넣어서 알려준다. 그러면 GetDetails 함수가 끝난 후 에피소드 페이지을 가지고 GetEpisodeList 함수가 불린다.

    6. GetEpisodeList 함수에서는 각 에피소드들의 기본정보(이름, 시즌, 에피소드 번호)와 각 에피소드들의 주소들을 추출한 후 리스트로 만든다.

    7. TV쇼 디렉토리있는 파일이름에서 부터 시즌, 에피소드 번호를 추출한 후 6에서 만들어진 리스트에 존재한다면 해당 주소를 가지고 GetEpisodeDetails를 호출한다.

    8. GetEpisodeDetails에서는 줄거리, 배우들의 보다 자세한 정보를 추출한다.


각 함수들은 하나 이상의 <RegExp>의 포함하고 있고, 이것은 input buffer, output buffer, regular expression 및 또다른 <RegExp>으로 구성되어 있다.

<expression>은 다음과 같은 parameter들을 가진다.

repeat   - (예: 여러명의 배우이름을 추출할 때)
noclean - HTML 문법을 남김 (예: 특정영역을 미리 뽑아낸 후, 그 안에서 다시 정보를 추출할 때 처음 결과에서 HTML 문장이 남아있어야 함)
trim - 앞뒤로 공백을 지움. 그러나 HTML과 연동이 되어서 실제 결과물에는 공백이 남아있을 수도 있다.
clear - expression 시작전에 출력버퍼 초기화. 앞 expression 출력과 동일한 출력을 사용할 때 유용하다.
encode - percent 인코딩
decode - percent 디코딩

Buffer들은 1-9번을 사용할 수 있는데 (사실 $10 이상도 사용가능함), 1~3 까지는 보통 입력으로 사용된다.

GetDetails 경우에 $1 은 HTML 내용, $2는 ID, $3 는 URL 이 저장되어있슴.


스크래퍼 커스텀 함수

기본 주소외에 다른 주소에서 정보를 가져와야 한다면 커스텀 함수를 만들어야 한다. 커스텀 함수는 다음 두가지가 있다.
       <url cache="file_name" function="function_name">address</url>
       <chain function="function_name">argument</url>
url 함수는 address에서 데이터를 읽어온 후 이를 function에서 처리한다. cache는 address가 재사용될 경우 로컬하드에 저장해놓고 재사용하기 위해서 이고, 한번만 불린다면 저정할 필요는 없다.
반면 chain은 argument를 function에서 처리한다.

스크래퍼 함수는 pre-processing 을 다시 하라는 것을 알려줄 뿐이기 때문에, 일반 함수와 의미가 다르다. 예를 들어 GetDetails 함수 중의 RegExp에서 함수를 호출해도 GetDetails를 모두 실행한 후 그 출력인 <details> 출력문을 뒤지며 <url>이 있는지 확인하고 그함수를 따로 호출한다. 그후 <url> 내용을 그 결과로 대체하는 형태이다. 따라서 각 함수에서는 버퍼가 매번 새로 정의된다고 보면 된다.

함수의 처리를 쉽게 하기 위해서 구조적으로 각 함수의 출력 형태를 제한하였다. 커스텀 함수는 불린 함수의 출력을 따르게 되어 있다. 예를 들어 GetDetails 함수에서 불리는 함수라면 <details></details>로 출력이 감싸져야 한다.

만약 출력문 외에도 다른 함수에게 정보를 넘기고 싶다면 함수의 parameter로 clearbuffers="no" 를 지정하면 된다. 예를 들어 Daum 영화페이지에서 사진은 여러 페이지에 걸쳐서 기록되어 있다. 각 페이지를 GetDaumFanart라는 함수로 처리할 경우 페이지 수만큼의 <fanart></fanart>가 생긴다. 문제는 스크래퍼에서는 <fanart> 하나만을 허용하기 때문에 첫번째 <fanart>만이 인식되게 된다. 따라서 마지막 페이지 전까지는 특정 버퍼에 결과를 모아놓고, 마지막 페이지 출력 때 모두 묶어서 하나의 <fanart>로 출력하는 방법이 사용된다.
참고로 이 방법은 트릭에 가깝기 때문에 오동작의 가능성도 크다.