데이터 스크랩(Data scraping)

자동실행파일 만들기(shell script 파일)

one-liner 까지 만들었다면, 이제 자동으로 실행해주는 스크립트 파일을 만들수 있습니다.

test.sh 라는 파일을 만들고, 이때까지 썼던 명령어를 하나로 이어서 입력해주고, 첫줄엔 shell 스크립트라는  정보를 입력해줍니다.

#!/bin/sh

curl -s 'https://projecteuler.net/archives'\
| scrape -be 'table#problems_table > tr:not(:first-child)' | xml2json \
| jq -c '.html.body.tr[] | {id: .td[0]."$t",subject: .td[1][]."$t",solved:.td[2][]."$t"}' \
| json2csv -p -k id,subject,solved > test_list.csv

 

권한설정하기

linux 파일은 -rwxrwxrwx 라는 속성이 있는데, 각각 r:읽기, w:쓰기, x:실행 을 의미하고, 

첫자리 -는 파일, d일경우는 폴더를 의미합니다.

처음 세자리 rwx는 user/owner
가운데 세자리 rwx는 group
오른쪽 세자리 rwx는 모든 사용자의 권한입니다.

파일을 만들고, 실행을 하려면, user에게 x(실행)권한을 줘야 합니다.

chmod u+x test.sh

u+x는 유저권한에 x를 추가하라는 의미입니다. (혹시 안되면 앞에 sudo를 붙여주세요.)

ls -al 을 해보면, x권한이 생겼을 겁니다.

실행은 ./test.sh 라고 입력해주면 됩니다. 파일명 앞에 현재폴더를 의미하는 점(.)과 슬래쉬(/)를 반드시 붙여줘야 합니다.

 

변수입력 & 반복실행 설정하기

불러오는 웹페이지가 한페이지가 아니라 여러페이지면, 변수설정과, 루프문을 통해서 자동으로 여러페이지의 데이터를 순식간에 처리할수 있습니다.

반복문의 형식은 아래와 같습니다.

for i in 1 2 3 4 5
do
~~~~~${i}~~~
~~~~~~~~~~~~
done

do 아래쪽에 반복실행할 코드를 작성하고 변수 i 를 ${i} 처럼 코드 중간에 입력을 해주면, 이부분의 숫자가 for문에서 설정한 범위에서 변하면서 코드가 실행됩니다.

페이지가 여러페이지일때, i변수를  페이지 번호를 의미하는 주소부분에다가 쓰면 되겠죠.

#!/bin/sh

for i in 1 2 3 4
do
curl -s 'https://projecteuler.net/archives;page=${i}'\
| scrape -be 'table#problems_table > tr:not(:first-child)' | xml2json \
| jq -c '.html.body.tr[] | {id: .td[0]."$t",subject: .td[1][]."$t",solved:.td[2][]."$t"}' \
| json2csv -p -k id,subject,solved > test_list.csv
done

한번 테스트 해보시면, 대체로 잘오는듯 보이지만, 몇가지 문제가 있습니다.

파일 이어쓰기

일단, 4페이지를 반복해서 데이터를 가져오긴 하는데, 같은 파일에 덮어써 버립니다. 즉 마지막 페이지 자료만 남죠. 그래서 파일을 덮어쓰지 않고, 파일끝에 이어서 쓰는 >> (괄호두개) 표시를 사용해야합니다. 이어쓰기를 하면, 해당 파일이 없을때는 생성을 해주고, 파일이 있으면 이어서 쓰기를 해줍니다.

#!/bin/sh

for i in 1 2 3 4
do
curl -s 'https://projecteuler.net/archives;page=${i}'\
| scrape -be 'table#problems_table > tr:not(:first-child)' | xml2json \
| jq -c '.html.body.tr[] | {id: .td[0]."$t",subject: .td[1][]."$t",solved:.td[2][]."$t"}' \
| json2csv -p -k id,subject,solved >> test_list.csv
done

네 괄호만 하나 추가해서 문제를 해결했네요. 그런데 파일내용을 잘보시면, 뭔가 좀 이상한부분이 있을겁니다.

csv 헤더 제거하기

4페이지를 반복하면서, 제목라인, 즉 헤더까지 반복이 되면서 섞여 들어간겁니다. json2csv 명령의 -p 옵션을 제거해주면, 4페이지 모두 제거되버리니, 가장 간단한 해결책은 루프문에서 첫번째 페이지만 따로 빼서 처리하는겁니다. 코드는 좀 길어지겠지만, 딱히 좋은 방법이 생각이 안나네요. 혹시 좋은방법을 알아내신분은 알려주세요. ㅎㅎ

#!/bin/sh

curl -s 'https://projecteuler.net/archives;page=1'\
| scrape -be 'table#problems_table > tr:not(:first-child)' | xml2json \
| jq -c '.html.body.tr[] | {id: .td[0]."$t",subject: .td[1][]."$t",solved:.td[2][]."$t"}' \
| json2csv -k id,subject,solved > test_list.csv

for i in 2 3 4
do
curl -s 'https://projecteuler.net/archives;page=${i}'\
| scrape -be 'table#problems_table > tr:not(:first-child)' | xml2json \
| jq -c '.html.body.tr[] | {id: .td[0]."$t",subject: .td[1][]."$t",solved:.td[2][]."$t"}' \
| json2csv -p -k id,subject,solved >> test_list.csv
done

 

댓글

댓글 본문