json 파일은 key와 value 로 구성되어 있습니다. jq 명령어를 통해, key 의 계층구조를 주소찾듯이 차례대로 지정해주면 value값을 찾아낼수 있습니다. https://stedolan.github.io/jq/
이 명령어가 사실상 핵심부분입니다. 웹페이지의 복잡도에 따라 이 명령어도 같이 복잡해집니다.
일단 파일을 대충 훑어본뒤에, 가져올 정보의 key값이 무엇인지 알아내야 합니다.
"html": {
"body": {
"tr": [
{
"td": [
{
"class": "id_column",
"$t": "1"
},
{
"a": {
"href": "problem=1",
"title": "Published on Friday, 5th October 2001, 06:00 pm",
"$t": "Multiples of 3 and 5"
}
},
{
"div": {
"style": "text-align:center;",
"$t": "768062"
}
}
]
},
html>body>tr
앞에서 추출한 json 파일을 살짝 들여다 보면, 우리가 가져올 정보(id의 숫자, title의 문자열, solved의 숫자)는 html 키 밑에 body 키 밑에 tr 키값 밑에 있고, tr키는 배열[ ]형태로 여러개의 tr값이 존재합니다. 그중에 첫번째 tr 키만 가져올려면,
< test_table.json jq -c '.html.body.tr[0]'
0번째, 즉 첫번째 tr 의 내용만 모두 출력이 됩니다.
html>body>tr>td
그 하위의 td 값까지 정해줄려면, td 역시 배열 형태 [ ] 로 3개가 존재하기 때문에, 0번째 td 만 출력하면
< test_table.json jq -c '.html.body.tr[0].td[0]'
{"class":"id_column","$t":"1"}
첫번째 tr의 첫번째td 블럭이 출력됩니다.
첫번째가 아닌 모든 tr 이나 td 를 출력하려면, 인덱스값을 주지말고 빈칸으로 놔두면 됩니다.
첫번째 tr의 모든td(3개)를 출력하려면,
< test_table.json jq -c '.html.body.tr[0].td[]'
{"class":"id_column","$t":"1"}
{"a":{"href":"problem=1","title":"Published on Friday, 5th October 2001, 06:00 pm","$t":"Multiples of 3 and 5"}}
{"div":{"style":"text-align:center;","$t":"768062"}}
모든 tr의 첫번째 td[0]만 출력하고 싶으면,
< test_table.json jq -c '.html.body.tr[].td[0]'
{"class":"id_column","$t":"1"}
{"class":"id_column","$t":"2"}
{"class":"id_column","$t":"3"}
{"class":"id_column","$t":"4"}
{"class":"id_column","$t":"5"}
{"class":"id_column","$t":"6"}
{"class":"id_column","$t":"7"}
{"class":"id_column","$t":"8"}
{"class":"id_column","$t":"9"}
{"class":"id_column","$t":"10"}
{"class":"id_column","$t":"11"}
....
아마 이런형태, 큰부분에서 루프를 돌면서, 공통적인 작은 부분만 골라내는 형태가 보통 최종적으로 원하는 형태가 될겁니다.
html>body>tr>td>id
그다음 좀더 세부적으로 들어가서, td 아래 id 값은 "$t"라는 키에 들어있습니다.
$t는 특수문자를 포함하고 있어서, 따옴표를 해줘야 합니다.
< test_table.json jq -c '.html.body.tr[].td[0]."$t"'
html>body>tr>td>a>title
그다음 title 값은 td[]에서 한단계 더 내려가서 a 태그 혹은 "a" 키값 아래에 "$t" 키에 있습니다.
(a 혹은 "a" 어떤형태로든 써줘도 됩니다.)
< test_table.json jq -c '.html.body.tr[].td[0]."a"."$t"'
html>body>tr>td> | id , a>title
id와 title 을 동시에 가져오려면
< test_table.json jq -c '.html.body.tr[] |.td[0]."$t", .td[1]."a"."$t"'
컴마로 차례로 연결해주면 되는데, 반복되는 앞부분은 파이프 앞부분에 써주고, 나머지 부분만 파이프 뒷부분에 써주면 됩니다.
결과를 json 형태로 표시하려면,
< test_table.json jq -c '.html.body.tr[] | {id:.td[0]."$t", title:.td[1]."a"."$t"'}
중괄호로 묶어주고, 각각의 출력값 앞에 key 값을 정해줄수 있습니다. 이 키값이 나중에 csv로 변환했을때 key값이 됩니다.
마찬가지로, 마지막solved 값도 동시에 가져올수 있습니다.
< test_table.json jq -c '.html.body.tr[] | {id:.td[0]."$t", title:.td[1]."a"."$t", solved:..td[2].div."$t"'}
세번째, solved 값은 td[2] 아래에 div 태그안에 들어있습니다.
{"id":"1","title":"Multiples of 3 and 5","solved":"768062"}
{"id":"2","title":"Even Fibonacci numbers","solved":"616688"}
{"id":"3","title":"Largest prime factor","solved":"441451"}
{"id":"4","title":"Largest palindrome product","solved":"392749"}
{"id":"5","title":"Smallest multiple","solved":"400765"}
{"id":"6","title":"Sum square difference","solved":"403170"}
{"id":"7","title":"10001st prime","solved":"345064"}
{"id":"8","title":"Largest product in a series","solved":"291209"}
{"id":"9","title":"Special Pythagorean triplet","solved":"294257"}
{"id":"10","title":"Summation of primes","solved":"269852"}
이 리스트가 두번째 추출의 결과물입니다.
이렇게 출력된 결과는 마찬가지로 test_list.json 파일로 저장해주겠습니다.
csv 파일로 변환하기(json2csv)
여기까지 변환됐으면, json2csv 명령으로 csv 파일로 변환해줄수 있습니다.
< test_table.json json2csv -k id,subject,solved > test_list.csv
-k 옵션은 변환할때 사용할 key 값만 지정해줄수 있습니다. 순서를 바꾸면, 출력할때 순서도 바껴서 출력됩니다.
1,Multiples of 3 and 5,768062
2,Even Fibonacci numbers,616688
3,Largest prime factor,441451
4,Largest palindrome product,392749
5,Smallest multiple,400765
6,Sum square difference,403170
7,10001st prime,345064
8,Largest product in a series,291209
9,Special Pythagorean triplet,294257
10,Summation of primes,269852
11,Largest product in a grid,195431
12,Highly divisible triangular number,182761
...
column 의 head 값을 붙여서 출력하려면 p 옵션을 붙여주면 됩니다.
< test_table.json json2csv -k id,subject,solved > test_list.csv
id,title,solved
1,Multiples of 3 and 5,768062
2,Even Fibonacci numbers,616688
3,Largest prime factor,441451
4,Largest palindrome product,392749
5,Smallest multiple,400765
6,Sum square difference,403170
7,10001st prime,345064
8,Largest product in a series,291209
9,Special Pythagorean triplet,294257
10,Summation of primes,269852
11,Largest product in a grid,195431
12,Highly divisible triangular number,182761
header를 붙였으면 csvlook 명령을 통해서 나름 보기좋게 출력도 가능합니다.
< test_list.csv csvlook
|-----+---------------------------------------+---------|
| id | title | solved |
|-----+---------------------------------------+---------|
| 1 | Multiples of 3 and 5 | 768062 |
| 2 | Even Fibonacci numbers | 616688 |
| 3 | Largest prime factor | 441451 |
| 4 | Largest palindrome product | 392749 |
| 5 | Smallest multiple | 400765 |
| 6 | Sum square difference | 403170 |
| 7 | 10001st prime | 345064 |
| 8 | Largest product in a series | 291209 |
...
...