Golang中Colly回调函数无法从go func接收变量的问题
Golang中Colly回调函数无法从go func接收变量的问题 基本上,情况是这样的:
x := "It worked earlyer lol"
go func(x string){
c.onHTML(...){
print(x)
}
c.visit(https://www.site.com)
}
这就是问题的核心。当我打印变量时,它们是空白的,但在 go 函数外部它们是有定义的。以下是完整的父函数:
eventCollector.OnHTML(".rgMasterTable tr", func(h *colly.HTMLElement) {
eventName := h.ChildText("td:nth-child(3) a")
eventURL := h.ChildAttr("td:nth-child(3) a", "href")
state := h.ChildText("td:nth-child(2)")
wgFR.Add(1) // 为每个 goroutine 增加 WaitGroup 计数器
semaphore <- struct{}{} // 获取一个令牌
go func(eventName, eventURL, state string) {
defer wgFR.Done() // goroutine 退出时发出完成信号
defer func() { <-semaphore }()
contestCollector := eventCollector.Clone()
var postedDateStr string
contestCollector.OnHTML("#ctl00_ContentPlaceHolder1_FormView1_Report_2Label", func(d *colly.HTMLElement) {
postedDateStr = d.Text
})
contestCollector.OnHTML(".rgMasterTable tr", func(c *colly.HTMLElement) { // 出问题的行
contestName := c.ChildText("td:nth-child(1)")
contestURL := c.ChildAttr("td:nth-child(3) a", "href")
if contestURL == "" {
contestURL = "FORMAT-ERROR"
} // 文档样式结果的临时处理程序
postedDate, timeErr := time.Parse("Jan 2, 2006", postedDateStr)
if timeErr != nil {
log.Printf("Error parsing time from %s", eventURL)
}
contest := Contest{
EventName: eventName,
ContestName: contestName,
PostedDate: postedDate,
ContestURL: contestURL,
State: state,
Present: true,
}
fResults = append(fResults, contest)
})
err := contestCollector.Visit("https://www.judgingcard.com/Results/" + eventURL)
if err != nil {
log.Printf("Could not find event: %s -- %s", eventURL, eventName)
}
contestCollector.Wait() // 等待内部收集器完成
}(eventName, eventURL, state)
})
在完整版本中,所有传递给 go 函数的变量在回调函数(contestCollector.OnHTML)内部都返回空白值。不幸的是,我不确定问题是在 goroutine 中,还是因为它是回调函数,或者是其他原因。
提前感谢!
更多关于Golang中Colly回调函数无法从go func接收变量的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这看起来相当复杂。看起来你正在使用 github.com/gocolly/colly。为什么那个部分要放在一个 goroutine 里呢?我建议先尝试去掉它。看起来收集器本身已经在使用 goroutines 了(我只是猜测,因为它们有一个 Wait 函数;我没有查阅文档来确认这一点)。
这段代码看起来缺少一些内容(比如你在哪里等待 wgFR?wgFR 甚至是在哪里定义的?),所以我的第一反应是,可能有些东西正在修改你外部函数中的字符串,而这可能是你没有预料到的。在有问题的 contestCollector.OnHTML 回调中,你没有将这些值传递给那个函数,所以它可能遇到了类似这样的问题:
func main() {
myAwesomeValue := "awesome"
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
time.Sleep(time.Millisecond)
fmt.Println("The value is", myAwesomeValue)
wg.Done()
}()
myAwesomeValue = "not awesome"
wg.Wait()
}
… 这段代码会打印出 The value is not awesome。
更多关于Golang中Colly回调函数无法从go func接收变量的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
感谢您,Colly框架确实有它自己的管理器,不需要定义新的等待组。根据我所学到的知识,我构建了这个测试脚本,它按预期工作。
package main
import (
"fmt"
"github.com/gocolly/colly"
)
type Event struct {
event_date string
state string
event_name string
event_url string
contest_name string
contest_url string
}
func main() {
var events []Event
ECollector := colly.NewCollector(colly.Async(true))
ECollector.Limit(&colly.LimitRule{DomainGlob: "*", Parallelism: 2})
ECollector.OnHTML(".rgMasterTable tr", func(e *colly.HTMLElement) {
if e.Index > 5 {
return
}
date := e.ChildText("td:nth-child(1)")
state := e.ChildText("td:nth-child(2)")
name := e.ChildText("td:nth-child(3)")
url := e.ChildAttr("td:nth-child(3) a", "href")
event := Event{
event_date: date,
state: state,
event_name: name,
event_url: url,
}
events = append(events, event)
})
ECollector.Visit("https://www.judgingcard.com")
ECollector.Wait()
CCollector := ECollector.Clone()
for _, event := range events {
CCollector.OnHTML(".rgMasterTable tr", func(c *colly.HTMLElement) {
//skip header line
if c.Index == 0 || c.Request.URL.String() == "https://www.judgingcard.com/Results/default.aspx" {
return
}
//More contests than events/build new struct
contest_name := c.ChildText("td:nth-child(1)")
contest_url := c.ChildAttr("td:nth-child(3) a", "href")
fmt.Println(contest_name, contest_url)
})
CCollector.Visit("https://www.judgingcard.com" + event.event_url)
}
CCollector.Wait()
}


