最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言結(jié)合正則表達(dá)式實(shí)現(xiàn)高效獲取數(shù)據(jù)

 更新時(shí)間:2025年04月28日 09:52:34   作者:Ai?編碼  
這篇文章主要為大家詳細(xì)介紹了Go語言如何結(jié)合正則表達(dá)式實(shí)現(xiàn)高效獲取數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

Go語言結(jié)合正則表達(dá)式可以構(gòu)建高效的數(shù)據(jù)爬取工具。下面我將提供幾個(gè)完整的實(shí)例,涵蓋不同場(chǎng)景下的數(shù)據(jù)爬取需求。

基礎(chǔ)網(wǎng)頁內(nèi)容爬取

1.1 獲取網(wǎng)頁中所有鏈接

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
)

func main() {
	// 發(fā)送HTTP請(qǐng)求
	resp, err := http.Get("https://example.com")
	if err != nil {
		fmt.Println("HTTP請(qǐng)求失敗:", err)
		return
	}
	defer resp.Body.Close()

	// 讀取響應(yīng)內(nèi)容
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("讀取響應(yīng)失敗:", err)
		return
	}

	// 編譯正則表達(dá)式,匹配所有a標(biāo)簽的href屬性
	re := regexp.MustCompile(`<a[^>]+href=["'](.*?)["']`)
	matches := re.FindAllStringSubmatch(string(body), -1)

	// 輸出所有鏈接
	fmt.Println("找到的鏈接:")
	for _, match := range matches {
		if len(match) > 1 {
			fmt.Println(match[1])
		}
	}
}

1.2 提取特定模式的文本

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
)

func main() {
	resp, err := http.Get("https://example.com")
	if err != nil {
		fmt.Println("HTTP請(qǐng)求失敗:", err)
		return
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)

	// 匹配所有<h1>-<h6>標(biāo)簽內(nèi)容
	re := regexp.MustCompile(`<h[1-6][^>]*>(.*?)</h[1-6]>`)
	titles := re.FindAllStringSubmatch(string(body), -1)

	fmt.Println("網(wǎng)頁標(biāo)題:")
	for _, title := range titles {
		if len(title) > 1 {
			// 去除HTML標(biāo)簽
			cleanTitle := regexp.MustCompile(`<[^>]+>`).ReplaceAllString(title[1], "")
			fmt.Println(cleanTitle)
		}
	}
}

結(jié)構(gòu)化數(shù)據(jù)爬取

2.1 爬取表格數(shù)據(jù)

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"
)

func main() {
	resp, err := http.Get("https://example.com/table-page")
	if err != nil {
		fmt.Println("HTTP請(qǐng)求失敗:", err)
		return
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	content := string(body)

	// 匹配整個(gè)表格
	tableRe := regexp.MustCompile(`<table[^>]*>(.*?)</table>`)
	tableMatch := tableRe.FindStringSubmatch(content)
	if len(tableMatch) == 0 {
		fmt.Println("未找到表格")
		return
	}

	tableContent := tableMatch[1]

	// 匹配表格行
	rowRe := regexp.MustCompile(`<tr[^>]*>(.*?)</tr>`)
	rows := rowRe.FindAllStringSubmatch(tableContent, -1)

	// 匹配單元格
	cellRe := regexp.MustCompile(`<t[dh][^>]*>(.*?)</t[dh]>`)

	fmt.Println("表格數(shù)據(jù):")
	for _, row := range rows {
		cells := cellRe.FindAllStringSubmatch(row[1], -1)
		for _, cell := range cells {
			if len(cell) > 1 {
				// 清理單元格內(nèi)容
				cleanCell := strings.TrimSpace(regexp.MustCompile(`<[^>]+>`).ReplaceAllString(cell[1], ""))
				fmt.Printf("%s\t", cleanCell)
			}
		}
		fmt.Println() // 換行
	}
}

2.2 爬取JSON數(shù)據(jù)中的特定字段

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
)

type Product struct {
	Name  string  `json:"name"`
	Price float64 `json:"price"`
}

func main() {
	resp, err := http.Get("https://api.example.com/products")
	if err != nil {
		fmt.Println("HTTP請(qǐng)求失敗:", err)
		return
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)

	// 方法1:直接解析JSON
	var products []Product
	if err := json.Unmarshal(body, &products); err == nil {
		fmt.Println("產(chǎn)品列表(JSON解析):")
		for _, p := range products {
			fmt.Printf("%s - $%.2f\n", p.Name, p.Price)
		}
		return
	}

	// 方法2:當(dāng)JSON結(jié)構(gòu)不確定時(shí)使用正則
	fmt.Println("\n嘗試使用正則表達(dá)式提取:")

	// 匹配產(chǎn)品名稱和價(jià)格
	re := regexp.MustCompile(`"name"\s*:\s*"([^"]+)"[^}]+"price"\s*:\s*(\d+\.?\d*)`)
	matches := re.FindAllStringSubmatch(string(body), -1)

	for _, match := range matches {
		if len(match) >= 3 {
			fmt.Printf("%s - $%s\n", match[1], match[2])
		}
	}
}

高級(jí)爬蟲技巧

3.1 帶并發(fā)控制的爬蟲

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"sync"
)

func main() {
	urls := []string{
		"https://example.com/page1",
		"https://example.com/page2",
		"https://example.com/page3",
	}

	var wg sync.WaitGroup
	semaphore := make(chan struct{}, 3) // 并發(fā)限制為3

	titleRe := regexp.MustCompile(`<title[^>]*>(.*?)</title>`)

	for _, url := range urls {
		wg.Add(1)
		go func(u string) {
			defer wg.Done()
			semaphore <- struct{}{} // 獲取信號(hào)量

			resp, err := http.Get(u)
			if err != nil {
				fmt.Printf("獲取 %s 失敗: %v\n", u, err)
				<-semaphore
				return
			}

			body, _ := ioutil.ReadAll(resp.Body)
			resp.Body.Close()

			title := titleRe.FindStringSubmatch(string(body))
			if len(title) > 1 {
				fmt.Printf("%s 的標(biāo)題: %s\n", u, title[1])
			}

			<-semaphore // 釋放信號(hào)量
		}(url)
	}

	wg.Wait()
}

3.2 處理分頁內(nèi)容

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strconv"
)

func main() {
	baseURL := "https://example.com/news?page="
	pageRe := regexp.MustCompile(`<div class="news-item">(.*?)</div>`)
	titleRe := regexp.MustCompile(`<h2>(.*?)</h2>`)
	pageNumRe := regexp.MustCompile(`page=(\d+)`)

	// 先獲取總頁數(shù)
	totalPages := getTotalPages(baseURL + "1")
	
	fmt.Printf("共發(fā)現(xiàn) %d 頁內(nèi)容\n", totalPages)

	// 爬取每頁內(nèi)容
	for page := 1; page <= totalPages; page++ {
		url := baseURL + strconv.Itoa(page)
		fmt.Printf("\n正在爬取第 %d 頁: %s\n", page, url)
		
		resp, err := http.Get(url)
		if err != nil {
			fmt.Printf("獲取第 %d 頁失敗: %v\n", page, err)
			continue
		}

		body, _ := ioutil.ReadAll(resp.Body)
		resp.Body.Close()

		newsItems := pageRe.FindAllStringSubmatch(string(body), -1)
		for _, item := range newsItems {
			if len(item) > 1 {
				title := titleRe.FindStringSubmatch(item[1])
				if len(title) > 1 {
					fmt.Println("新聞標(biāo)題:", title[1])
				}
			}
		}
	}
}

func getTotalPages(url string) int {
	resp, err := http.Get(url)
	if err != nil {
		return 1 // 默認(rèn)1頁
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	
	// 假設(shè)頁面中有類似 "共 5 頁" 的文字
	re := regexp.MustCompile(`共\s*(\d+)\s*頁`)
	match := re.FindStringSubmatch(string(body))
	if len(match) > 1 {
		total, _ := strconv.Atoi(match[1])
		return total
	}
	
	return 1
}

實(shí)用技巧與注意事項(xiàng)

1.User-Agent設(shè)置:

client := &http.Client{}
req, _ := http.NewRequest("GET", "https://example.com", nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; MyBot/1.0)")
resp, _ := client.Do(req)

2.處理相對(duì)鏈接:

import "net/url"

base, _ := url.Parse("https://example.com")
rel, _ := url.Parse("/page1")
absURL := base.ResolveReference(rel).String()

3.正則表達(dá)式優(yōu)化:

預(yù)編譯正則表達(dá)式:re := regexp.MustCompile(pattern)

使用非貪婪匹配:.*?

避免過度復(fù)雜的正則表達(dá)式

4.錯(cuò)誤處理增強(qiáng):

resp, err := http.Get(url)
if err != nil {
    return fmt.Errorf("請(qǐng)求失敗: %w", err)
}
defer func() {
    if err := resp.Body.Close(); err != nil {
        log.Printf("關(guān)閉響應(yīng)體失敗: %v", err)
    }
}()

反爬蟲策略應(yīng)對(duì)

設(shè)置合理的請(qǐng)求間隔:

import "time"

func crawlWithDelay(urls []string, delay time.Duration) {
    for _, url := range urls {
        go crawlPage(url)
        time.Sleep(delay)
    }
}

使用代理IP:

proxyUrl, _ := url.Parse("http://proxy-ip:port")
client := &http.Client{
    Transport: &http.Transport{
        Proxy: http.ProxyURL(proxyUrl),
    },
}
resp, _ := client.Get("https://example.com")

處理Cookies:

jar, _ := cookiejar.New(nil)
client := &http.Client{Jar: jar}
// 第一次請(qǐng)求獲取cookie
client.Get("https://example.com/login")
// 后續(xù)請(qǐng)求會(huì)攜帶cookie
client.Get("https://example.com/protected-page")

總結(jié)

以上實(shí)例展示了Go語言結(jié)合正則表達(dá)式進(jìn)行數(shù)據(jù)爬取的多種方法:

  • 基礎(chǔ)網(wǎng)頁爬?。韩@取鏈接、提取特定內(nèi)容
  • 結(jié)構(gòu)化數(shù)據(jù)提?。罕砀駭?shù)據(jù)、JSON數(shù)據(jù)
  • 高級(jí)技巧:并發(fā)控制、分頁處理
  • 實(shí)用技巧:User-Agent設(shè)置、相對(duì)鏈接處理
  • 反爬應(yīng)對(duì):請(qǐng)求間隔、代理IP、Cookies處理

在實(shí)際項(xiàng)目中,建議:

  • 對(duì)于結(jié)構(gòu)化數(shù)據(jù)優(yōu)先使用API而非HTML解析
  • 復(fù)雜的HTML解析考慮使用goquery等專門庫
  • 遵守網(wǎng)站的robots.txt規(guī)則
  • 設(shè)置合理的爬取頻率,避免對(duì)目標(biāo)網(wǎng)站造成負(fù)擔(dān)

這些實(shí)例可以作為基礎(chǔ)模板,根據(jù)具體需求進(jìn)行調(diào)整和擴(kuò)展。

到此這篇關(guān)于Go語言結(jié)合正則表達(dá)式實(shí)現(xiàn)高效獲取數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Go獲取數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用go操作redis的有序集合(zset)

    使用go操作redis的有序集合(zset)

    這篇文章主要介紹了使用go操作redis的有序集合(zset),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go語言中nil判斷引起的問題詳析

    Go語言中nil判斷引起的問題詳析

    這篇文章主要給大家介紹了關(guān)于Go語言中nil判斷引起問題的相關(guān)資料,nil 是Go語言中一個(gè)預(yù)定義好的標(biāo)識(shí)符,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-06-06
  • 使用 go 實(shí)現(xiàn)多線程下載器的方法

    使用 go 實(shí)現(xiàn)多線程下載器的方法

    本篇文章帶領(lǐng)大家學(xué)習(xí)使用go實(shí)現(xiàn)一個(gè)簡(jiǎn)單的多線程下載器,給她家詳細(xì)介紹了多線程下載原理及實(shí)例代碼,感興趣的朋友跟隨小編一起看看吧
    2021-10-10
  • Go語言中錯(cuò)誤處理實(shí)例分析

    Go語言中錯(cuò)誤處理實(shí)例分析

    這篇文章主要介紹了Go語言中錯(cuò)誤處理,實(shí)例分析了Go語言中針對(duì)錯(cuò)誤處理的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • golang 如何獲取pem格式RSA公私鑰長(zhǎng)度

    golang 如何獲取pem格式RSA公私鑰長(zhǎng)度

    這篇文章主要介紹了golang 如何獲取pem格式RSA公私鑰長(zhǎng)度操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go net/http/pprof分析內(nèi)存泄露及解決過程

    Go net/http/pprof分析內(nèi)存泄露及解決過程

    這篇文章主要介紹了Go net/http/pprof分析內(nèi)存泄露及解決過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Go作用域的理解

    Go作用域的理解

    在Go語言中,作用域是指變量的可見性范圍,它定義了變量在程序中的生命周期和可訪問性,本文主要介紹了Go作用域的理解,包括局部作用域、全局作用域、命名空間作用域等,感興趣的可以了解一下
    2023-11-11
  • 關(guān)于go平滑重啟庫overseer實(shí)現(xiàn)原理詳解

    關(guān)于go平滑重啟庫overseer實(shí)現(xiàn)原理詳解

    這篇文章主要為大家詳細(xì)介紹了關(guān)于go平滑重啟庫overseer實(shí)現(xiàn)原理,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,有需要的小伙伴可以參考下
    2023-11-11
  • Go開發(fā)go-optioner工具實(shí)現(xiàn)輕松生成函數(shù)選項(xiàng)模式代碼

    Go開發(fā)go-optioner工具實(shí)現(xiàn)輕松生成函數(shù)選項(xiàng)模式代碼

    go-optioner?是一個(gè)在?Go?代碼中生成函數(shù)選項(xiàng)模式代碼的工具,可以根據(jù)給定的結(jié)構(gòu)定義自動(dòng)生成相應(yīng)的選項(xiàng)代碼,下面就來聊聊go-optioner是如何使用的吧
    2023-07-07
  • 詳解Go是如何優(yōu)雅的進(jìn)行內(nèi)存管理

    詳解Go是如何優(yōu)雅的進(jìn)行內(nèi)存管理

    Go語言拋棄C/C++中的開發(fā)者管理內(nèi)存的方式,實(shí)現(xiàn)了主動(dòng)申請(qǐng)與主動(dòng)釋放管理,增加了逃逸分析和垃圾回收,將開發(fā)者從內(nèi)存管理中釋放出來,作為進(jìn)階的Go開發(fā),了解掌握Go的內(nèi)存管理還是很有必要的
    2023-09-09

最新評(píng)論

天门市| 平山县| 西乌珠穆沁旗| 江都市| 明星| 怀远县| 万山特区| 苏尼特右旗| 黄石市| 乃东县| 宁武县| 怀来县| 新野县| 怀宁县| 无锡市| 夏河县| 铜川市| 荆州市| 温宿县| 中江县| 剑阁县| 长宁区| 霍邱县| 嘉禾县| 阳春市| 乡城县| 合山市| 洪江市| 武胜县| 瑞安市| 泽库县| 房产| 普兰店市| 屏东县| 阿尔山市| 寿光市| 安乡县| 郓城县| 永春县| 乌拉特后旗| 嫩江县|