-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
137 lines (117 loc) · 2.79 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package main
import (
"bufio"
"fmt"
"net"
"net/http"
"os"
"strings"
"sync"
"golang.org/x/net/html"
)
// Website represents a website to scrape
type Website struct {
URL string
Title string
IPAddress string
}
// scrapeWebsite fetches the title and IP address of a website
func scrapeWebsite(url string, wg *sync.WaitGroup, websiteCh chan<- Website) {
defer wg.Done()
// Fetch title
title, err := scrapeTitle(url)
if err != nil {
fmt.Println("Error fetching title for", url, ":", err)
title = "N/A"
}
// Fetch IP address
ipAddr, err := fetchIPAddress(url)
if err != nil {
fmt.Println("Error fetching IP address for", url, ":", err)
ipAddr = "N/A"
}
// Send the website information to the channel
websiteCh <- Website{URL: url, Title: title, IPAddress: ipAddr}
}
// scrapeTitle fetches the title of a website
func scrapeTitle(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
doc, err := html.Parse(resp.Body)
if err != nil {
return "", err
}
var title string
var traverse func(*html.Node)
traverse = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "title" {
title = n.FirstChild.Data
return
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
traverse(c)
}
}
traverse(doc)
return title, nil
}
// fetchIPAddress fetches the IP address of a website
func fetchIPAddress(url string) (string, error) {
host := extractHost(url)
ipAddr, err := net.LookupIP(host)
if err != nil {
return "", err
}
return ipAddr[0].String(), nil
}
// extractHost extracts the host from a URL
func extractHost(url string) string {
parts := strings.Split(url, "//")
if len(parts) > 1 {
return parts[1]
}
return parts[0]
}
func main() {
var urls []string
fmt.Println("Enter URLs (one per line), type 'done' when finished:")
scanner := bufio.NewScanner(os.Stdin)
for {
var url string
if !scanner.Scan() {
break
}
url = scanner.Text()
if url == "done" {
break
}
// Check if the URL has a scheme, if not, prepend "https://"
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
url = "https://" + "www." + url
}
urls = append(urls, url)
}
if err := scanner.Err(); err != nil {
fmt.Println("Error reading input:", err)
return
}
var wg sync.WaitGroup
websiteCh := make(chan Website)
// Start a goroutine for each URL to scrape the website information concurrently
for _, url := range urls {
wg.Add(1)
go scrapeWebsite(url, &wg, websiteCh)
}
// Close the channel when all goroutines are done
go func() {
wg.Wait()
close(websiteCh)
}()
// Collect website information from the channel
for website := range websiteCh {
fmt.Printf("URL: %s, Title: %s, IP Address: %s\n", website.URL, website.Title, website.IPAddress)
}
}