pub trait SelectorBase { fn from_html>(html: S) -> Self; fn html(&self) -> String; fn css>(&self, css_selector: S) -> Vec { let html = nipper::Document::from(self.html().as_str()); let mut output = vec![]; for item in html.select(css_selector.as_ref()).iter() { output.push(Selector::from_html(item.html().to_string())) } output } fn css_once>(&self, css_selector: S) -> Option { self.css(css_selector.as_ref()).pop() } fn xpath>(&self, xpath: S) -> Vec { match cssifier::cssifier(xpath.as_ref()) { Some(css_selector) => { if css_selector.is_empty() { Vec::default() } else { self.css(css_selector.as_str()) } } None => Vec::default(), } } fn xpath_once>(&self, xpath: S) -> Option { self.xpath(xpath.as_ref()).pop() } fn content(&self) -> String { let html = nipper::Document::from(self.html().as_str()); html.select("body > *") .iter() .map(|element| element.text().to_string()) .last() .unwrap() } fn attr<'a>(&self, attribute: &'a str) -> Option { let html = nipper::Document::from(self.html().as_str()); html.select(" body > *") .attr(attribute) .map(|text| text.to_string()) } } #[derive(Debug)] pub struct Selector { text: String, } impl SelectorBase for Selector { fn from_html>(html: S) -> Self { Selector { text: html.as_ref().to_string(), } } fn html(&self) -> String { self.text.clone() } }