golang并发爬取本网站
涉及到解析html的扩展是goquery 可以去git下载就好了 本程序主要是两个线程
一个线程爬取分页的详情链接 然后把链接相关数据 存进chan
另一线程从chan拿取详情链接 获取详情数据 然后把数据存进去另一个chan 最后插入数据库
package main import ( "fmt" "regexp" "log" "net/http" "github.com/PuerkitoBio/goquery" "strings" "github.com/jmoiron/sqlx" _ "github.com/go-sql-driver/mysql" ) //数据格式 type Pdata struct { title string `json:"title"` href string `json:"href"` author string `json:"author"` text string `json:"text"` } //var Db func Init() *sqlx.DB { db,err := sqlx.Open(`mysql`,"root:xt@tcp(127.0.0.1:3306)/test") if err != nil{ log.Print(err.Error()) } return db } func InsertData(allData []Pdata)(){ Db := Init() for _,value := range allData{ _,err := Db.Exec("insert into jjj set title = ?,href = ?,author = ?,content = ?",value.title,value.href,value.author,value.text) log.Print(err) } } //解析页面返回的数据 func getData(ch chan Pdata){ for i := 1;i < 16;i++{ href := fmt.Sprintf("http://phpindex.win/?page=%d",i) resp := getHrefData(href) doc, _ := goquery.NewDocumentFromResponse(resp) doc.Find(".auth1").Each(func(i int, selection *goquery.Selection) { var tempD Pdata tempD.title = selection.Find("header > h2").Text() href,_ := selection.Find("header > h2 > a").Attr("href") tempD.href = href author := getRegexp(selection.Find("footer > h5 > em").Eq(0).Text(),"作者:(.+)") tempD.author = author ch <- tempD }) } close(ch) log.Print("获取列表结束") } //获取详情数据 func getDetailsData(ch chan Pdata,allData chan Pdata) { for v := range ch{ href := fmt.Sprintf(v.href) index := strings.Index(href, "http") if index == -1{ continue } resp := getHrefData(href) doc, _ := goquery.NewDocumentFromResponse(resp) text := doc.Find(".auth1 > section").Text() v.text = text allData <- v } close(allData) log.Print("获取详情结束") // 这段代码效果一样 // for{ // if v,ok:=<-ch;ok==true{ // href := fmt.Sprintf(v.href) // index := strings.Index(href, "http") // if index == -1{ // continue // } // resp := getHrefData(href) // // doc, _ := goquery.NewDocumentFromResponse(resp) // // text := doc.Find(".auth1 > section").Text() // // v.text = text // allData <- v // }else { //通道关闭 // //fmt.Println(num) // break // } //} // //close(allData) //log.Print("获取详情结束") } //获取页面数据返回解析 func getHrefData(href string) *http.Response { client := &http.Client{} req, err := http.NewRequest("GET",href, nil) if err != nil { log.Fatal(err) } resp, err := client.Do(req) if err != nil { log.Fatal(err) } return resp } //通过正则提取数据 func getRegexp(ss,regexpS string) string { r, _ := regexp.Compile(regexpS) dd := r.FindStringSubmatch(ss) if len(dd) < 2{ return "" } return dd[1] } func main() { ch := make(chan Pdata,10) allData := make(chan Pdata,5) var allDataInsert []Pdata go getData(ch)//获取第一层的数据 go getDetailsData(ch,allData)//获取详情的数据 //这里也可以弄成并发 for v := range allData{ allDataInsert = append(allDataInsert, v) } InsertData(allDataInsert) log.Print("结束") //log.Print(allData) }