c 抓取网页数据(Colly学习笔记(三)——爬虫框架,抓取动态页面 )
优采云 发布时间: 2022-04-12 10:28c 抓取网页数据(Colly学习笔记(三)——爬虫框架,抓取动态页面
)
Colly 学习笔记(三) - 爬虫框架,抓取动态页面
Colly学习笔记(一)-爬虫框架,捕捉中金行业市盈率数据
Colly学习笔记(二)-爬虫框架,抓取下载数据
Colly学习笔记(三) - 爬虫框架,抓取动态页面数据
前两章主要讨论静态数据的爬取。我们只需要将网页地址栏中的url传递给get请求,就可以轻松获取网页的数据。但是,有些网页是动态页面。我们传递网页的源代码。翻页时找不到数据,网址也没有变化。此时无法获取数据。比如下图,通过开发者工具,查看网页源码,发现虽然URL相同,但内容不同。此时需要找到动态页面对应的URL,才能抓取数据。
查看页面真实URL的方法如下:
点击分页按钮找到对应的URL(具体步骤如图)
通过postman查看和排除无效参数
#动态URL原始参数
http://query.sse.com.cn/security/stock/getStockListData2.do?&jsonCallBack=jsonpCallback49711&isPagination=true&stockCode=&csrcCode=&areaName=&stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=3&pageHelp.pageSize=25&pageHelp.pageNo=3&pageHelp.endPage=31&_=1609296745917
#postman调试优化后的参数
http://query.sse.com.cn/security/stock/getStockListData2.do?stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=3&pageHelp.pageSize=25&pageHelp.pageNo=3
postman 视图如下图
写colly代码抓取流程
//finish
c.OnScraped(func(r *colly.Response) {
//解析Json
var item PageResult
err := json.Unmarshal(r.Body, &item)
if err != nil {
receiver.MLog.GetLogHandle().WithFields(log.Fields{"err":err,"res":string(r.Body)}).Error("Receive Error ")
//若返回系统繁忙,则等一段时间重新访问
if strings.Contains(string(r.Body),"error"){
c.Visit(url)
}
}
//
if len(item.Result) > 1{
res = append(res,&item)
receiver.MLog.GetLogHandle().WithFields(log.Fields{"item":item}).Info("Receive message ")
return
}
//第一次只取一条是为了获取所有的A股总数,然后重新一次获取到所有数据,无需多次分页
SubUrl := "http://query.sse.com.cn/security/stock/getStockListData2.do?stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=1&pageHelp.pageSize="
SubUrl += strconv.Itoa(item.Page.Total)
c.Visit(SubUrl)
})
结果:
完整代码如下:
package main
import (
"encoding/json"
"fmt"
"github.com/gocolly/colly"
log "github.com/sirupsen/logrus"
"strconv"
"strings"
)
type pageHelp struct {
Total int `json:"total"`
}
type pageResult struct {
CompanyAbbr string `json:"COMPANY_ABBR"`
CompanyCode string `json:"COMPANY_CODE"`
EnglishAbbr string `json:"ENGLISH_ABBR"`
ListingTime string `json:"LISTING_DATE"`
MoveTime string `json:"QIANYI_DATE"`
}
type PageResult struct {
AreaName string `json:"areaName"`
Page pageHelp `json:"pageHelp"`
Result []pageResult `json:"result"`
StockType string `json:"stockType"`
}
func (receiver Collector) ScrapeJs(url string) (error,[]*PageResult) {
receiver.MLog.GetLogHandle().WithFields(log.Fields{"URL":url}).Info("URL...")
c := colly.NewCollector(colly.UserAgent(RandomString()),colly.AllowURLRevisit())
c.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36"
res := make([]*PageResult, 0)
c.OnRequest(func(r *colly.Request) {
//r.Headers.Set("User-Agent", RandomString())
r.Headers.Set("Host", "query.sse.com.cn")
r.Headers.Set("Connection", "keep-alive")
r.Headers.Set("Accept", "*/*")
r.Headers.Set("Origin", "http://www.sse.com.cn")
//关键头 如果没有 则返回 错误
r.Headers.Set("Referer", "http://www.sse.com.cn/assortment/stock/list/share/")
r.Headers.Set("Accept-Encoding", "gzip, deflate")
r.Headers.Set("Accept-Language", "zh-CN,zh;q=0.9")
receiver.MLog.GetLogHandle().WithFields(log.Fields{"Request":fmt.Sprintf("%+v",*r),"Headers":fmt.Sprintf("%+v",*r.Headers)}).Info("Begin Visiting...")
})
c.OnError(func(_ *colly.Response, err error) {
receiver.MLog.GetLogHandle().WithFields(log.Fields{"error":err}).Info("Something went wrong:")
})
c.OnResponse(func(r *colly.Response) {
receiver.MLog.GetLogHandle().WithFields(log.Fields{"Headers":r.Headers}).Info("Receive Header")
})
//scraped item from body
//finish
c.OnScraped(func(r *colly.Response) {
var item PageResult
err := json.Unmarshal(r.Body, &item)
if err != nil {
receiver.MLog.GetLogHandle().WithFields(log.Fields{"err":err,"res":string(r.Body)}).Error("Receive Error ")
if strings.Contains(string(r.Body),"error"){
c.Visit(url)
}
}
if len(item.Result) > 1{
res = append(res,&item)
receiver.MLog.GetLogHandle().WithFields(log.Fields{"item":item}).Info("Receive message ")
return //结束递归
}
SubUrl := "http://query.sse.com.cn/security/stock/getStockListData2.do?stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=1&pageHelp.pageSize="
SubUrl += strconv.Itoa(item.Page.Total)
c.Visit(SubUrl)
})
c.Visit(url)
return nil,res
}
func (receiver Collector) ScrapeJsTest() error {
//第一次只获取一条数据目的是为了获取数据总条数,下次递归拼接URL一次获取所有数据
UrlA := "http://query.sse.com.cn/security/stock/getStockListData2.do?stockType=1&pageHelp.cacheSize=1&pageHelp.pageSize=1&pageHelp.beginPage=1"
receiver.ScrapeJs(UrlA)
return nil
}
func main() {
var c Collector
c.MLog=receiver.MLog
c.ScrapeJsTest()
return
}