Go使用colly爬取数据时如何在GraphQL Resolver返回完整Article数组
问题修复方案
问题原因
- 回调函数内部新建了局部切片
articleModel,完全没有操作外部声明的articles变量,最终返回的切片自然为空 - 你开启了
colly.Async()异步模式,OnHTML的回调会在独立的goroutine中执行,直接对切片做append操作是非并发安全的,即使你写入外部切片也可能出现数据丢失
修复后代码
import "sync" // 原有Article结构体定义保持不变 type Article struct { Title string `bson:"title"` Source string `bson:"source"` Url string `bson:"url"` Timestamp string `bson:"timestamp"` } func (r *RootResolver) News() ([]models.Article, error) { c := colly.NewCollector( colly.MaxDepth(2), colly.Async(), ) c.Limit(&colly.LimitRule{Parallelism: 10}) articles := []models.Article{} var mu sync.Mutex // 新增互斥锁保证并发写入安全 c.OnHTML("article", func(e *colly.HTMLElement) { article := models.Article{ Title: e.ChildText("h3 a"), Source: e.ChildText("a[data-n-tid]"), Timestamp: e.ChildAttr("div:last-child time", "datetime"), // 可选优化:如果拿到的是相对路径,可转成绝对路径 // Url: e.Request.AbsoluteURL(e.ChildAttr("a[href]", "href")), Url: e.ChildAttr("a[href]", "href"), } // 加锁后写入外部切片 mu.Lock() articles = append(articles, article) mu.Unlock() }) c.Visit(SOMEURLHERE) c.Wait() return articles, nil }
核心修改说明
- 移除回调内局部的
articleModel切片,直接构造单个Article实例 - 新增
sync.Mutex互斥锁,每次写入articles切片前加锁,写入完成后解锁,避免并发写入导致的数据异常 - 将构造好的文章实例追加到外部声明的
articles切片中,爬取到的数据就会被正常保留到返回结果里
内容的提问来源于stack exchange,提问作者user16663541
相关产品推荐
相关产品推荐

