-
Notifications
You must be signed in to change notification settings - Fork 0
/
rakugokai.lisp
66 lines (62 loc) · 2.89 KB
/
rakugokai.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
(defpackage #:rakugokyokai-parser/rakugokai
(:use #:cl
#:rakugokyokai-parser/utils
#:lquery)
(:import-from #:assoc-utils
#:aget)
(:export #:parse-rakugokai))
(in-package #:rakugokyokai-parser/rakugokai)
(defvar *base-uri*
"http://rakugo-kyokai.jp/rakugokai/detail.php")
(defun parse-table (table)
(when (plump:node-p table)
(loop for tr across (plump:child-elements table)
append
(coerce
(let ((class (plump:get-attribute tr "class")))
(cond
((equal class "Performers")
($ tr (combine "th" "td")
(map-apply (lambda (th td)
(cons ($1 th (render-text))
(coerce ($ td "a"
(combine (attr "href") (render-text))
(map-apply (lambda (href text)
`(("name" . ,text)
("uri" . ,(merge-uris href *base-uri*))))))
'list))))))
((equal class "OtherPerformers")
($ tr (combine "th" "td")
(map-apply (lambda (th td)
(cons ($1 th (render-text))
(ppcre:split "[\\s,、 ]+" ($1 td (render-text))))))))
((< 0 (length ($ tr "td table")))
($ tr (combine "th" "td table")
(map-apply (lambda (th table)
(cons ($1 th (render-text))
(parse-table (aref table 0)))))))
(t
($ tr (combine ".Caption, .caption" ".confirm-text")
(map-apply (lambda (th td)
(cons ($1 th (render-text))
($1 td (render-text)))))))))
'list))))
(defun %parse-rakugokai-html (body)
(let* ((main ($1 (initialize body) ".main .contents"))
(title ($1 main "h2" (render-text)))
(body ($1 main ".rakugokai table")))
`(("title" . ,title)
,@(parse-table body))))
(defun parse-rakugokai (body)
(let ((res (%parse-rakugokai-html body)))
`(("title" . ,(aget res "title"))
("start-date" . ,(aget res "開催日"))
("start-time" . ,(aget res "開演"))
,@(let ((place (aget res "会場")))
`(("place" . ,(aget place "名称"))
("address" . ,(aget place "住所"))))
("performers" . ,(append
(aget res "出演者(協会員)")
(mapcar (lambda (name)
`(("name" . ,name)))
(aget res "出演者(その他)")))))))