Есть примерно вот такой кусок кода парсера сайта с использованием select:
extern crate select;
use select::document::Document;
use select::predicate::{Class, Name, And};
fn main() {
// Пример; реальность чуть сложнее, но не суть
let html = "<main>
<div class='vote-topic'>
<div class='vote-item vote-count'>
<span id='vote_total_blog_123'>+15.00</span>
</div>
</div>
</main>";
let page = Document::from(html);
let blog_id: u32 = page.find(And(Name("div"),Class("vote-item")))
.find(Name("span")).first()
.unwrap().attr("id")
.unwrap().split('_').collect::<Vec<_>>().last()
.unwrap().parse::<u32>().unwrap();
println!("Blog id: {}", blog_id);
}
Я попытался его переписать так, чтобы на выходе получить Option (который потом переведу в Result; конкретно здесь сохранение точной причины ошибки не интересует). Результат работает, но выглядит, мягко говоря, не очень:
let blog_id: Option<u32> = page.find(And(Name("div"),Class("vote-item"))).first()
.and_then(|x| x.find(Name("span")).first())
.and_then(|x| x.attr("id").and_then(|x| Some(x.to_string())))
.and_then(|x| x.split('_').collect::<Vec<_>>().last().and_then(|x| Some(x.to_string())))
.and_then(|x| x.parse::<u32>().ok());
match blog_id {
Some(i) => println!("Blog id: {}", i),
None => println!("Cannot parse blog_id"),
};
Возможно ли оформить это как-нибудь более красиво? Если я пытаюсь это как-нибудь упрощать (особенно противный to_string), компилятор незамедлительно начинает ругаться на времена жизни, заимствования и прочую дребедень. Использование match или if let, подозреваю, приведёт к зашкаливающему количеству лесенок, а если их избегать, то красивость всё равно не особо увеличится. Ещё я пытался написать макрос с циклом, эквивалентный постоянным вызовам and_then, но получилось так же некрасиво и to_string никуда не делись.
В идеале что-нибудь похоже на такой Python-эквивалент:
try:
blog_id = int(page.find("div", {"class": "vote-item"}).\
find("span")[0].\
get("id").\
rsplit("_")[-1])
except Exception:
blog_id = None
(наверно, лучше просто взять xpath, но вопрос пока не про это :)
Еще в ночном расте можно использовать оператор
– aSpex Nov 03 '16 at 20:52?вместоtry!.