Add OpenSearch and SearchPage functionality for DuckDuckGo
Introduced the `OpenSearch` method and `SearchPage` interface to streamline search operations and allow for loading more results dynamically. Updated dependencies and modified the DuckDuckGo CLI to utilize these enhancements.
This commit is contained in:
68
sites/duckduckgo/page.go
Normal file
68
sites/duckduckgo/page.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package duckduckgo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.stevedudenhoeffer.com/steve/go-extractor"
|
||||
"io"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type SearchPage interface {
|
||||
io.Closer
|
||||
GetResults() []Result
|
||||
LoadMore() error
|
||||
}
|
||||
|
||||
type searchPage struct {
|
||||
doc extractor.Document
|
||||
}
|
||||
|
||||
func (s searchPage) GetResults() []Result {
|
||||
var res []Result
|
||||
var err error
|
||||
|
||||
err = s.doc.ForEach(`article[id^="r1-"]`, func(n extractor.Node) error {
|
||||
var r Result
|
||||
|
||||
links := n.Select(`a[href][target="_self"]`)
|
||||
|
||||
if len(links) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
r.URL, err = links[0].Attr(`href`)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get link: %w", err)
|
||||
}
|
||||
|
||||
titles := n.Select("h2")
|
||||
|
||||
if len(titles) != 0 {
|
||||
r.Title, _ = titles[0].Text()
|
||||
}
|
||||
|
||||
descriptions := n.Select("span > span")
|
||||
|
||||
if len(descriptions) != 0 {
|
||||
r.Description, _ = descriptions[0].Text()
|
||||
}
|
||||
|
||||
res = append(res, r)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (s searchPage) LoadMore() error {
|
||||
return s.doc.ForEach(`button#more-results`, func(n extractor.Node) error {
|
||||
slog.Info("clicking load more", "node", n)
|
||||
return n.Click()
|
||||
})
|
||||
}
|
||||
|
||||
func (s searchPage) Close() error {
|
||||
return s.doc.Close()
|
||||
}
|
Reference in New Issue
Block a user