init
This commit is contained in:
commit
f9082aa509
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.DS_Store
|
26
LICENSE
Normal file
26
LICENSE
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
MIT NON-AI License
|
||||||
|
|
||||||
|
Copyright (c) 2024, Frank Mayer
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of the software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions.
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
In addition, the following restrictions apply:
|
||||||
|
|
||||||
|
1. The Software and any modifications made to it may not be used for the purpose of training or improving machine learning algorithms,
|
||||||
|
including but not limited to artificial intelligence, natural language processing, or data mining. This condition applies to any derivatives,
|
||||||
|
modifications, or updates based on the Software code. Any usage of the Software in an AI-training dataset is considered a breach of this License.
|
||||||
|
|
||||||
|
2. The Software may not be included in any dataset used for training or improving machine learning algorithms,
|
||||||
|
including but not limited to artificial intelligence, natural language processing, or data mining.
|
||||||
|
|
||||||
|
3. Any person or organization found to be in violation of these restrictions will be subject to legal action and may be held liable
|
||||||
|
for any damages resulting from such use.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module github.com/tsukinoko-kun/lwb
|
||||||
|
|
||||||
|
go 1.23.2
|
||||||
|
|
||||||
|
require golang.org/x/net v0.32.0 // indirect
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
||||||
|
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
107
main.go
Normal file
107
main.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package lwb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/tsukinoko-kun/lwb/util"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Browser struct {
|
||||||
|
url string
|
||||||
|
userAgent string
|
||||||
|
document *html.Node
|
||||||
|
mut sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
Element struct {
|
||||||
|
node *html.Node
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewBrowser(userAgent string) *Browser {
|
||||||
|
b := &Browser{
|
||||||
|
userAgent: userAgent,
|
||||||
|
}
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Browser) Get(url string) error {
|
||||||
|
b.mut.Lock()
|
||||||
|
defer b.mut.Unlock()
|
||||||
|
|
||||||
|
b.url = url
|
||||||
|
|
||||||
|
rest, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer rest.Body.Close()
|
||||||
|
|
||||||
|
b.document, err = html.Parse(rest.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Browser) GetElementById(id string) *Element {
|
||||||
|
b.mut.RLock()
|
||||||
|
defer b.mut.RUnlock()
|
||||||
|
|
||||||
|
var nodes util.Stack[*html.Node] = []*html.Node{b.document}
|
||||||
|
for !nodes.Empty() {
|
||||||
|
node := nodes.Pop()
|
||||||
|
for _, a := range node.Attr {
|
||||||
|
if strings.ToLower(a.Key) != "id" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if a.Val != id {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return &Element{node: node}
|
||||||
|
}
|
||||||
|
|
||||||
|
for c := node.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
nodes.Push(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Browser) GetElementsByClassName(class string) []*Element {
|
||||||
|
b.mut.RLock()
|
||||||
|
defer b.mut.RUnlock()
|
||||||
|
|
||||||
|
var elements []*Element
|
||||||
|
var nodes util.Stack[*html.Node] = []*html.Node{b.document}
|
||||||
|
for !nodes.Empty() {
|
||||||
|
node := nodes.Pop()
|
||||||
|
attr_loop:
|
||||||
|
for _, a := range node.Attr {
|
||||||
|
if strings.ToLower(a.Key) != "class" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, c := range classNames(a.Val) {
|
||||||
|
if c == class {
|
||||||
|
elements = append(elements, &Element{node: node})
|
||||||
|
break attr_loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for c := node.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
nodes.Push(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func classNames(class string) []string {
|
||||||
|
return strings.Split(class, " ")
|
||||||
|
}
|
21
util/stack.go
Normal file
21
util/stack.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
type Stack[T any] []T
|
||||||
|
|
||||||
|
func (s *Stack[T]) Push(v T) {
|
||||||
|
*s = append(*s, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stack[T]) Pop() T {
|
||||||
|
v := (*s)[len(*s)-1]
|
||||||
|
*s = (*s)[:len(*s)-1]
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Stack[T]) Peek() T {
|
||||||
|
return s[len(s)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Stack[T]) Empty() bool {
|
||||||
|
return len(s) == 0
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user