84 lines
1.9 KiB
Go
84 lines
1.9 KiB
Go
// Parser for Google Translate
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"golang.org/x/net/html"
|
|
)
|
|
|
|
func doRequest(settings *TranslateSettings, reqUrl string) (*http.Response, error) {
|
|
client := &http.Client{}
|
|
|
|
if settings.proxy != nil {
|
|
tr := &http.Transport{Proxy: http.ProxyURL(settings.proxy)}
|
|
client.Transport = tr
|
|
}
|
|
|
|
req, err := http.NewRequest("GET", reqUrl, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header["User-Agent"] = []string{settings.userAgent}
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
return resp, err
|
|
}
|
|
|
|
// Requests and parses translation from Google
|
|
func Translate(settings *TranslateSettings, fromLang, toLang, text string) (string, error) {
|
|
// Escape parameters before embedding in URL
|
|
fromLang = url.QueryEscape(fromLang)
|
|
toLang = url.QueryEscape(toLang)
|
|
text = url.QueryEscape(text)
|
|
|
|
reqUrl := fmt.Sprintf("https://translate.google.com/m?sl=%s&tl=%s&q=%s", fromLang, toLang, text)
|
|
|
|
resp, err := doRequest(settings, reqUrl)
|
|
if err != nil {
|
|
return "", fmt.Errorf("Request failed: %v", err)
|
|
}
|
|
|
|
doc, err := html.Parse(resp.Body)
|
|
if err != nil {
|
|
return "", fmt.Errorf("HTML parsing failed: %v", err)
|
|
}
|
|
|
|
res, err := walk(doc)
|
|
if err != nil {
|
|
return "", fmt.Errorf("Error parsing translation page: %v", err)
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func walk(node *html.Node) (string, error) {
|
|
// Check if element has a class of result-container
|
|
if node.Type == html.ElementNode && node.Data == "div" {
|
|
for _, attr := range node.Attr {
|
|
if attr.Key == "class" && attr.Val == "result-container" {
|
|
// Retrieve the content of it
|
|
if content := node.FirstChild; content != nil {
|
|
return content.Data, nil
|
|
} else {
|
|
return "", fmt.Errorf("result-container is empty")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Recursively walk through subelements
|
|
for c := node.FirstChild; c != nil; c = c.NextSibling {
|
|
if res, err := walk(c); err == nil {
|
|
return res, err
|
|
}
|
|
}
|
|
|
|
return "", fmt.Errorf("no result")
|
|
}
|