ЗАДАЧА
Для работы с данными из веба надо сначало извлечь их. Затем сконвертировать в объекты, понимаемые R. Поскольку содержание страниц может меняться, надо как - то автоматизировать сбор данных, по возможности сделав его устойчивым к изменению страницы или, по крайней мере, легко модифицируемым.
РЕШЕНИЕ
Полностью автоматизировать сбор, основываясь, например, на регулярности элементов DOM не получится - слишком часто встречаются тучи без смысла вложенных TABLE. Поэтому я сделал ставку на визуальное выделение "интересных" элементов страницы с последующим назначением инструкций по их обработке.
Для работы плагина нужен прокси, чтобы добавить в тело страницы строчки:
script src="scripts/jquery.js" type="text/javascript"
script src="scripts/jqDnR.js" type="text/javascript"
script src="scripts/selector.rule.js" type="text/javascript"
а также загрузить сами сценарии из scripts/. Можно обойтись и без jqDnR.js - функциональность небольшая, а мороки много. Кое - что я сам поправил - убрал прозрачность (были из - за неё проблемы). С остальным разбираться - нет знаний и желания.
Плагин работает неторопливо, поэтому, в частности, два режима работы. В одном клик на навигационной панели приводит к прыжку (откату выделения), в другом - к предпросмотру содержимого элемента.
/*
* SelectorRule - jQuery plugin for a quick navigation over
* html tree
*
* Author: dimiii
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Version: r1
*
*/
(function($) {
var style = {
tasks_panel : {
"position" : "absolute", "zIndex" : "500", "width" : "75%",
"padding" : "5px", "margin" : "0px",
"background-color" : "#eff", "border" : "1px solid #999",
"textAlign" : "left"
},
hint_area : {
"padding" : "5px", "margin" : "5px", "width" : "95%",
"height" : "200px",
"background-color" : "#eff", "border" : "1px dotted"
},
cmd_area : {
"padding" : "5px", "margin" : "5px",
"width" : "50%", "height" : "80px",
"border" : "1px dotted"
},
mouseover : {
"border" : "2px solid lime"
},
mouseclick : {
"border" : "3px solid green"
}
};
/*
Node selector contains
*/
$.fn.nodeSelector = function() {
var click_trace = [];
var tasks_panel = null;
if (!tasks_panel) {
tasks_panel = $() // It seems blogger doesn't understand pre tag.
// So here is a commented tasks_panel's skeleton.
.appendTo("BODY")
.hide()
.bind("click", function(e) {
e.stopPropagation();
});
$(this).bind("contextmenu", function(e) {
display(tasks_panel, e, click_trace);
activate_actions(tasks_panel, click_trace);
return false;
});
}
mk_clickable(document.body, click_trace);
return this;
};
function display(tasks_panel, e, click_trace) {
$(".jqHandle").css("background-color", "lightgrey");
$("#panel_stuff")
.empty()
.append(get_mode_slctr())
.append(get_jump_nav(click_trace, true))
.append(get_hint_text(click_trace))
.append(get_command_panel())
.append(get_btns());
$("A")
.css({"font-weight" : "bold",
"text-decoration" : "none", "color" : "black"})
.bind("mouseover", function() { $(this).css("color", "red"); })
.bind("mouseout",
function() { $(this).css("color", "black"); });
tasks_panel
.css(style.tasks_panel)
.css({"left":0.15* document.width,"top":e.pageY})
.show();
};
function activate_actions(tasks_panel, click_trace)
{
$(".jump_nav")
.bind("click",
function() {
if ("selected" == $("#jumpModeBtn").attr("class")) {
var clcked = click_trace[$(this).attr("id")],
trace_pos = click_trace.pop();
while(trace_pos != clcked) {
$(trace_pos.childNodes).each(
function() { brk_clickable(this); });
$(trace_pos).css({"border" : trace_pos.cssMemo || ""});
trace_pos = click_trace.pop();
}
click_trace.push(clcked);//back
$(clcked.childNodes).each(
function() { mk_clickable(this, click_trace); });
tasks_panel.hide();
} else {
$("#hint_area")
.empty()
.append($(click_trace[$(this).attr("id")]).text());
}
});
$("#closeBtn")
.bind("click", function(){ tasks_panel.hide(); });
$("#commitBtn")
.bind("click", function(){
alert(get_jump_nav(click_trace, false));
tasks_panel.hide(); });
$("#insPathBtn")
.bind("click",
function(){ $("#cmd_area")
.append(get_jump_nav(click_trace, false)); });
$("#jumpModeBtn")
.bind("click",
function() {
if("selected" != $(this).attr("class")) {
$(this).empty().append("[jump]").addClass("selected");
$("#viewModeBtn")
.empty().append("view").removeClass("selected");
}
});
$("#viewModeBtn")
.bind("click",
function() {
if("selected" != $(this).attr("class")) {
$(this)
.empty().append("[view]").addClass("selected");
$("#jumpModeBtn")
.empty().append("jump").removeClass("selected");
}
});
tasks_panel.jqDrag(".jqDrag");
};
function mk_clickable(docnode, click_trace) {
if ($(docnode).attr("id") == "tasks_panel") return;
switch (docnode.nodeName.toString().toLowerCase()) {
// we can't make clickable tbody and tr,
// so let's make clickable their childs
case "tbody":
case "tr":
$(docnode.childNodes).each(
function() { mk_clickable(this, click_trace); });
break;
case "body":
case "div":
case "p":
case "span":
case "a":
case "table":
case "td":
try {
docnode.cssMemo = $(docnode).css("border");
}catch(exc){}
$(docnode)
.bind("mouseover",
function() { $(this).css(style.mouseover); })
.bind("mouseout",
function() { $(this).css({"border" : docnode.cssMemo
|| ""}); })
.bind("click",
function() {
click_trace.push(this);
$(this).css(style.mouseclick);
switch(docnode.parentNode.nodeName.toString()
.toLowerCase()) {
case "tbody":
case "tr":
$(docnode.parentNode.parentNode.childNodes).each(
function() { brk_clickable(this); });
break;
default:
$(docnode.parentNode.childNodes).each(
function() { brk_clickable(this); });
break;
}
$(docnode.childNodes).each(
function() { mk_clickable(this, click_trace); });
});
break;
}
};
function brk_clickable(docnode) {
switch(docnode.nodeName.toString().toLowerCase()) {
case "tbody":
case "tr": // reasons like for mk_clickable
$(docnode.childNodes).each(
function() { brk_clickable(this); });
break;
default:
$(docnode)
.unbind("mouseover").unbind("click").unbind("mouseout");
break;
}
};
/*
Implementations of other functions are skipped.
*/
})(jQuery);
$(function() {
$("BODY A").attr("href", "#");// defence
$("BODY A").unbind("click", function() { mk_clickable(this);} );
$("BODY").nodeSelector();
});
Инструкции предполагается записывать на DSL или непосредственно на R. Окончательный выбор сделаю после более подробного знакомства с библиотекой XML.
ВЫВОД
Работает и каши не просит.
БОНУС
Сегодня, через весьма насыщенный http://twit88.com узнал о существовании http://web-harvest.sourceforge.net. Основательный подход, но пока я никаких преимуществ перед моим "тынц-тынц" методом не вижу. Всё же, следует знать.
четверг, 6 декабря 2007 г.
День четвёртый (web harvesting)
на
12:47
Подписаться на:
Комментарии к сообщению (Atom)

Комментариев нет:
Отправить комментарий