Skip to main content

headless_engine/google/
parser.rs

1use crate::dom::DomTree;
2use crate::google::types::{GenericGoogleResult, GoogleAutocompleteResult, GoogleSearchResult, OrganicResult};
3use serde_json::Value;
4
5pub struct GoogleParser;
6
7impl GoogleParser {
8    pub fn parse_search_results(html: &str, url: &str) -> GoogleSearchResult {
9        let dom = match DomTree::parse(html) {
10            Ok(d) => d,
11            Err(_) => return GoogleSearchResult {
12                query: url.to_string(),
13                title: "Google Search (Parse Error)".to_string(),
14                ..Default::default()
15            }
16        };
17        
18        let title = dom.extract(Some("title")).unwrap_or_else(|| "Google Search".to_string());
19        
20        // This leverages the existing SearchResults logic implicitly or we build it explicitly.
21        let search_results = dom.parse_google_search_results();
22        
23        let mut organic = Vec::new();
24        for res in search_results.organic_results {
25            organic.push(OrganicResult {
26                title: res.title,
27                link: res.link,
28                snippet: res.snippet,
29            });
30        }
31        
32        GoogleSearchResult {
33            query: url.to_string(), // In a real app we'd parse the URL q= param
34            title,
35            ai_overview: search_results.ai_overview.map(|a| a.summary),
36            knowledge_panel: search_results.knowledge_panel.map(|k| k.description),
37            organic_results: organic,
38            related_questions: search_results.related_questions,
39        }
40    }
41
42    pub fn parse_autocomplete(json: &str) -> GoogleAutocompleteResult {
43        if let Ok(val) = serde_json::from_str::<Value>(json) {
44            if let Some(arr) = val.as_array() {
45                if arr.len() >= 2 {
46                    if let Some(query) = arr[0].as_str() {
47                        if let Some(suggestions) = arr[1].as_array() {
48                            let mut suggs = Vec::new();
49                            for s in suggestions {
50                                if let Some(s_str) = s.as_str() {
51                                    suggs.push(s_str.to_string());
52                                }
53                            }
54                            return GoogleAutocompleteResult {
55                                query: query.to_string(),
56                                suggestions: suggs,
57                            };
58                        }
59                    }
60                }
61            }
62        }
63        GoogleAutocompleteResult::default()
64    }
65
66    pub fn parse_generic(html: &str, url: &str) -> GenericGoogleResult {
67        let dom = match DomTree::parse(html) {
68            Ok(d) => d,
69            Err(_) => return GenericGoogleResult {
70                query: url.to_string(),
71                title: "Parse Error".to_string(),
72                raw_markdown: "Error parsing HTML".to_string(),
73            }
74        };
75        let title = dom.extract(Some("title")).unwrap_or_else(|| "Google Result".to_string());
76        let md = dom.extract_markdown(None, Some(url));
77        GenericGoogleResult {
78            query: url.to_string(),
79            title,
80            raw_markdown: md,
81        }
82    }
83}