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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
mod error; pub use error::*; pub use xpather::{ self, Document, Node, Value }; pub trait ScraperMain: Sized { fn scrape(doc: &Document, container: Option<Node>) -> Result<Self>; } pub fn evaluate<S: Into<String>>(search: S, doc: &Document, container: Option<Node>) -> Option<Value> { if let Some(node) = container { doc.evaluate_from(search, node) } else { doc.evaluate(search) } } pub trait ConvertFromValue<T>: Sized { fn convert_from(self, doc: &Document) -> Result<T>; } impl ConvertFromValue<Option<String>> for Option<Value> { fn convert_from(self, _: &Document) -> Result<Option<String>> { Ok(if let Some(value) = self { value_to_string(&value) } else { None }) } } impl ConvertFromValue<String> for Option<Value> { fn convert_from(self, _: &Document) -> Result<String> { Ok(if let Some(value) = self { value_to_string(&value).ok_or(Error::ConvertFromValue(Some(value)))? } else { return Err(Error::ConvertFromValue(None)); }) } } impl ConvertFromValue<Vec<String>> for Option<Value> { fn convert_from(self, _: &Document) -> Result<Vec<String>> { Ok(if let Some(value) = self { value_to_string_vec(value) } else { Vec::new() }) } } impl<T> ConvertFromValue<Vec<T>> for Option<Value> where T: ScraperMain { fn convert_from(self, doc: &Document) -> Result<Vec<T>> { Ok(if let Some(value) = self.map(|v| v.into_iterset()).transpose()? { value.map(|n| T::scrape(doc, Some(n))).collect::<Result<Vec<_>>>()? } else { Vec::new() }) } } pub fn value_to_string(value: &Value) -> Option<String> { match value { Value::Nodeset(set) => { set.nodes.first() .and_then(|n| value_to_string(&n.value())) } Value::String(v) => Some(v.clone()), _ => None } } pub fn value_to_string_vec(value: Value) -> Vec<String> { match value { Value::Nodeset(set) => { set.nodes.into_iter().filter_map(|n| value_to_string(&n.value())).collect() } Value::String(v) => vec![v], _ => Vec::new() } }