Advertisement
dereksir

Untitled

May 13th, 2024 (edited)
915
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.74 KB | None | 0 0
  1. // import necessary crates
  2. extern crate html5ever;
  3. extern crate reqwest;
  4.  
  5. use std::default::Default;
  6.  
  7. // import necessary modules from html5ever
  8. use html5ever::tendril::*;
  9. use html5ever::tokenizer::BufferQueue;
  10. use html5ever::tokenizer::{TagToken, StartTag, EndTag};
  11. use html5ever::tokenizer::{Token, TokenSink, TokenSinkResult, Tokenizer, TokenizerOpts,};
  12. use html5ever::tokenizer::CharacterTokens;
  13.  
  14. // define a struct to hold the state of the parser
  15. struct TokenPrinter {
  16.     // define flags to track token location.
  17.     in_price_tag: bool,  
  18.     in_span_tag: bool,  
  19.     in_bdi_tag: bool,    
  20.     price: String,       // string to hold the price
  21. }
  22.  
  23. // implement the TokenSink trait for TokenPrinter
  24. impl TokenSink for TokenPrinter {
  25.     type Handle = ();
  26.  
  27.     // define function to process each token in the HTML document
  28.     fn process_token(&mut self, token: Token, _line_number: u64) -> TokenSinkResult<()> {
  29.         match token {
  30.             TagToken(tag) => {
  31.                 // if the token is a start tag...
  32.                 if tag.kind == StartTag {
  33.                     // ...and the tag is a <p> tag with class "price"...
  34.                     if tag.name.to_string() == "p" {
  35.                         for attr in tag.attrs {
  36.                             if attr.name.local.to_string() == "class" && attr.value.to_string() == "price" {
  37.                                 // ...set the in_price_tag flag to true
  38.                                 self.in_price_tag = true;
  39.                             }
  40.                         }
  41.                     // if we're inside a <p class="price"> tag and the tag is a <span> tag...
  42.                     } else if self.in_price_tag && tag.name.to_string() == "span" {
  43.                         // ...set the in_span_tag flag to true
  44.                         self.in_span_tag = true;
  45.                     // if we're inside a <p class="price"> tag and the tag is a <bdi> tag...
  46.                     } else if self.in_price_tag && tag.name.to_string() == "bdi" {
  47.                         // ...set the in_bdi_tag flag to true
  48.                         self.in_bdi_tag = true;
  49.                     }
  50.                 // if the token is an end tag...
  51.                 } else if tag.kind == EndTag {
  52.                     // ...and the tag is a <p>, <span>, or <bdi> tag...
  53.                     if tag.name.to_string() == "p" {
  54.                         // ...set the corresponding flag to false
  55.                         self.in_price_tag = false;
  56.                     } else if tag.name.to_string() == "span" {
  57.                         self.in_span_tag = false;
  58.                     } else if tag.name.to_string() == "bdi" {
  59.                         self.in_bdi_tag = false;
  60.                     }
  61.                 }
  62.             },
  63.             // if the token is a character token (i.e., text)...
  64.             CharacterTokens(s) => {
  65.                 // ...and we're inside a <p class="price"> tag...
  66.                 if self.in_price_tag {
  67.                     // ...and we're inside a <span> tag...
  68.                     if self.in_span_tag {
  69.                         // ...add the text to the price string
  70.                         self.price = format!("price: {}", s);
  71.                     // ...and we're inside a <bdi> tag...
  72.                     } else if self.in_bdi_tag {
  73.                         // ...append the text to the price string and print it
  74.                         self.price = format!("{}{}", self.price, s);
  75.                         println!("{}", self.price);
  76.                         // clear the price string for the next price
  77.                         self.price.clear();
  78.                     }
  79.                 }
  80.             },        
  81.             // ignore all other tokens
  82.             _ => {},
  83.         }
  84.         // continue processing tokens
  85.         TokenSinkResult::Continue
  86.     }    
  87. }
  88.  
  89. #[tokio::main]
  90. async fn main() -> Result<(), Box<dyn std::error::Error>> {
  91.     // initialize the TokenPrinter
  92.     let sink = TokenPrinter { in_price_tag: false, in_span_tag: false, in_bdi_tag: false, price: String::new() };
  93.  
  94.     // retrieve HTML content from target website
  95.     //... let resp = reqwest::get("https://www.scrapingcourse.com/ecommerce/product/adrienne-trek-jacket/").await?.text().await?;
  96.  
  97.     // convert the HTML content to a ByteTendril
  98.     let chunk = ByteTendril::from(resp.as_bytes());
  99.     let mut input = BufferQueue::new();
  100.     input.push_back(chunk.try_reinterpret::<fmt::UTF8>().unwrap());
  101.  
  102.     // initialize the Tokenizer with the TokenPrinter
  103.     let mut tok = Tokenizer::new(
  104.         sink,
  105.         TokenizerOpts::default(),
  106.     );
  107.     // feed the HTML content to the Tokenizer
  108.     let _ = tok.feed(&mut input);
  109.     assert!(input.is_empty());
  110.     // end tokenization
  111.     tok.end();
  112.  
  113.     Ok(())
  114. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement