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
| package main
import ( "context" "fmt" "net/http" "os" "sync" "time"
"golang.org/x/net/html" )
func fetchTitle(ctx context.Context, url string) (string, error) { startTime := time.Now() req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { return "", err }
resp, err := http.DefaultClient.Do(req) if err != nil { return "", err } defer resp.Body.Close()
if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("bad status: %s", resp.Status) }
doc, err := html.Parse(resp.Body) if err != nil { return "", err }
var title string var f func(*html.Node) f = func(n *html.Node) { if n.Type == html.ElementNode && n.Data == "title" && n.FirstChild != nil { title = n.FirstChild.Data } for c := n.FirstChild; c != nil; c = c.NextSibling { f(c) } } f(doc)
elapsedTime := time.Since(startTime).Round(time.Millisecond) return title + " (" + elapsedTime.String() + ")", nil }
func crawlURLs(ctx context.Context, urls []string) ([]string, error) { var wg sync.WaitGroup wg.Add(len(urls))
titles := make(chan string, len(urls)) for _, url := range urls { go func(url string) { defer wg.Done() title, err := fetchTitle(ctx, url) if err != nil { fmt.Printf("Error fetching %s: %v\n", url, err) titles <- "Error: " + err.Error() return } titles <- title }(url) }
wg.Wait() close(titles)
resultTitles := make([]string, 0, len(urls)) for title := range titles { resultTitles = append(resultTitles, title) }
return resultTitles, nil }
func main() { urls := []string{ "https://www.baidu.com", "https://www.36kr.com", "https://www.sina.com.cn", "https://www.jd.com", "https://www.taobao.com", "https://www.pinduoduo.com", "https://www.tmall.com", "https://www.zhihu.com", "http://www.juejin.cn", "https://www.aliyun.com", }
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel()
titles, err := crawlURLs(ctx, urls) if err != nil { fmt.Println("Error:", err) os.Exit(1) }
for i, title := range titles { fmt.Printf("%d: %s\n", i+1, title) } }
|