Предыдущие: Большие письма в Gmail, Упражнение на сложение (LATEX)
Он запихивает ваш ЖЖ в базу данных.
(Зачем это делать тоже ясно - SQL нам расскажет всё о нашем (или чужом) ЖЖ - темы, комменты, таги - насколько фантазии хватит собирать статистику)
Сначало нам надо скачать ЖЖ в XML.
Это сделает чужая утилита - ljdump
Придется установить Питон, открыть IDLE (Python GUI), загрузить туда утилиту и запустить. Всё спросит она сама.
После её пробега у вас будет директория с файлами LXXX - посты и CXXX - комменты.
А на эти XMLи мы и запустим мой скрипт.
В этом виде он использует pure Java, embedded базу данных Hypersonic (HSQLDB), но можно подключиться к любой, конечно же. Только убедитесь, что JDBC driver у вас в classpath.
На примере этого скипта легко увидеть как изящно в груви можно парсить XML.
Только это, конечно же годится именно для скриптов. В энтерпрайзе никто не будет загружать весь XML в память (а будут использовать SAX),и никто не будет напрямую слать SQL (а будет Connection Pool, prepared statement, batch, Hibernate какой нибудь).
Вот скрипт:
import groovy.sql.Sql import java.sql.Timestamp def sql = Sql.newInstance("jdbc:hsqldb:file:lj", "sa", "", "org.hsqldb.jdbcDriver") // delete table if previously created try { sql.execute("drop table POST")} catch (Exception e) {} try { sql.execute("drop table COMMENT")} catch (Exception e) {} // create table sql.execute('''create table POST ( id integer not null primary key, url varchar(100), subject varchar(100), text varchar(10000), postdate timestamp )''') sql.execute('''create table COMMENT ( id integer not null primary key, postid integer, user varchar(100), subject varchar(100), text varchar(10000), commentdate timestamp, parentcomment integer )''') sql.execute(''' alter table COMMENT add constraint c ''') def dir = "D:\\development\\ljdump-1.5.1\\javax_sl List<File> files = new File(dir).listFiles().findAll { it.name.startsWith("L") } files.each { record -> def event = new XmlSlurper().parse(record) int id = Integer.parseInt(event.itemid.text()) Date d = Date.parse("yyy-MM-dd HH:mm:ss", event.eventtime.text()) //No time zone java.sql.Timestamp sqlDate = new java.sql.Timestamp(d.time) String url = event.url.text() String subject = event.subject.text() String text = event.event.text() sql.execute("insert into post (id,url,subject, text, File commentsFile = new File(dir + record.name.replace('L', 'C')); if (commentsFile.exists()) { def comments = new XmlSlurper().parse(commentsFile).comment comments.each() { comment -> String state = comment.state.text() if (!"D".equals(state)) { // not deleted int commentid = Integer.parseInt(comment.id.text()) String user = comment.user.text() String parentIdStr = comment.parentid.text() int parentid = 0; if (!parentIdStr.isEmpty()) Integer.parseInt(parentIdStr) Date commentDate = Date.parse("yyy-MM-dd HH:mm:ss", comment.date.text().replace('T',' ')) //No time zone Timestamp sqlCommentTime = new Timestamp(commentDate.time) String commentsubject = comment.subject.text(); String body = comment.body.text() sql.execute("insert into comment (id,user,subject,te } } } } sql.close(); |
Конечно же его можно улучшить:
1. Сохранять автора поста (Важно, если парсите комьюнити)
2. Сделать чтобы получал директорию с файлами и URL базы данных как аргумент
Можно улучшить схему:
1. Сохранять таги
2. Хранить авторов в отдельной таблице
3. Добавить индексы
Можно добавить директиву @Grab, чтобы не надо было добавлять драйверы в classpath (я пробывал, у меня не получилось :( )
Теперь глянем как это использовать.
Составим список моих постов у которых больше 50 комментов:
@Grab('hsqldb:hsqldb:1.8.0.7') import groovy.sql.Sql Sql sql = Sql.newInstance("jdbc:hsqldb:file:lj", "sa", "", "org.hsqldb.jdbcDriver") sql.eachRow("select subject, url, (select count { row -> if (row.numcom>50) println row} |
Результат:
[SUBJECT:Что меня бесит, URL:http://javax-slr.livejournal.com/324397.html, NUMCOM:142]
[SUBJECT:1, URL:http://javax-slr.livejournal.com/329453.html, NUMCOM:137]
[SUBJECT:Вступление, URL:http://javax-slr.livejournal.com/55396.html, NUMCOM:91]
[SUBJECT:Альтернативная история, URL:http://javax-slr.livejournal.com/375084.html, NUMCOM:73]
[SUBJECT:Матрица компетентности программиста, URL:http://javax-slr.livejournal.com/229088.html, NUMCOM:69]
[SUBJECT:Источники радости, URL:http://javax-slr.livejournal.com/330862.html, NUMCOM:65]
[SUBJECT:Опросник на общий контекст: флэшмоб, URL:http://javax-slr.livejournal.com/192595.html, NUMCOM:65]
[SUBJECT:Степень двойки, URL:http://javax-slr.livejournal.com/292479.html, NUMCOM:61]
[SUBJECT:ДНК генеалогия, URL:http://javax-slr.livejournal.com/283962.html, NUMCOM:57]
[SUBJECT:Если бы вы жили в ..., URL:http://javax-slr.livejournal.com/387338.html, NUMCOM:55]
[SUBJECT:Рабоче-карьерное, URL:http://javax-slr.livejournal.com/264434.html, NUMCOM:53]
[SUBJECT:Мир тесен., URL:http://javax-slr.livejournal.com/91867.html, NUMCOM:53]