Go语言 StackOverflow的最大速率限制

hts6caw3  于 2023-01-10  发布在  Go
关注(0)|答案(1)|浏览(146)

我一直试图访问StackOverflow的数量为30请求/秒,但它不工作。它已被封锁后,几秒钟。虽然StackOverflow的文件说,StackExchange的最大速率限制是30请求/秒。
我用来访问的库是gocolly这里是我的代码:

package main

import (
    "fmt"
    "log"
    "strconv"

    "time"

    "github.com/gocolly/colly"
    "github.com/gocolly/colly/debug"
)

func finish() {
    fmt.Println("Finish")
}

func main() {
    c := colly.NewCollector(
        colly.AllowedDomains("stackoverflow.com"),
        colly.MaxDepth(1),
        colly.Async(true),
        colly.Debugger(&debug.LogDebugger{}),
    )

    c.Limit(&colly.LimitRule{DomainGlob: "*stackoverflow.*", Parallelism: 10, Delay: 1 * time.Second})
    c.OnRequest(func(r *colly.Request) {
        r.Headers.Set("User-Agent", "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
    })

    c.OnError(func(_ *colly.Response, err error) {
        log.Println("Something went wrong:", err)
    })

    c.OnResponse(func(r *colly.Response) {
        fmt.Println("Visited", r.Request.URL)
    })
    c.OnHTML("#questions", func(e *colly.HTMLElement) {
        e.ForEach(".s-post-summary.js-post-summary", func(i int, el *colly.HTMLElement) {
            link := el.ChildAttr("a[href]", "href")
            e.Request.Visit("https://stackoverflow.com" + link)
        })
    })

    for i := 0; i <= 1000; i++ {
        
       var link = "https://stackoverflow.com/questions?tab=votes&page=" + strconv.Itoa(i)
       c.Visit(link)
       c.Wait()

    }

    finish()
}

我希望有人能帮助我。

2lpgd968

2lpgd9681#

很遗憾,我无法在我的计算机上重现您的问题。顺便说一句,我将指出一些可以改进您的解决方案的事项。首先,让我分享一下我的工作解决方案:

package main

import (
    "fmt"
    "log"
    "strconv"
    "time"

    "github.com/gocolly/colly/v2"
)

func finish() {
    fmt.Println("Finish")
}

func main() {
    c := colly.NewCollector(
        colly.AllowedDomains("stackoverflow.com"),
        colly.MaxDepth(1),
        colly.Async(true),
        // colly.Debugger(&debug.LogDebugger{}),
    )

    c.Limit(&colly.LimitRule{DomainGlob: "*stackoverflow.*", Parallelism: 8, Delay: 1 * time.Second})
    c.OnRequest(func(r *colly.Request) {
        r.Headers.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
    })

    c.OnError(func(_ *colly.Response, err error) {
        log.Println("Something went wrong:", err)
    })

    c.OnResponse(func(r *colly.Response) {
        fmt.Println("Visited", r.Request.URL)
    })
    c.OnHTML("#questions", func(e *colly.HTMLElement) {
        e.ForEach(".s-post-summary.js-post-summary", func(i int, el *colly.HTMLElement) {
            link := el.ChildAttr("a[href]", "href")
            e.Request.Visit("https://stackoverflow.com" + link)
        })
    })

    for i := 0; i <= 29; i++ {
        link := "https://stackoverflow.com/questions?tab=votes&page=" + strconv.Itoa(i)
        c.Visit(link)
    }

    c.Wait()
    finish()
}

所做的更改包括:
1.潜在并发线程从10减少到8
1.使用我的User-Agent值。
1.将c.Wait调用置于for循环之外。
最后一个修改是最重要的,因为你误解了它的用法。基本上,它等待之前创建的所有线程(例如,根据你的机器,你可能有8并发线程处理你的爬网请求)。如果你把这个语句放在循环中,每次你只等待刚刚示例化的线程导致同步操作。
尝试几次就能很容易地注意到,如果把c.Wait留在for循环中,你会注意到页面是以有序的方式访问的;如果把这条语句从for循环中去掉,页面是以无序的方式访问的。
让我知道,如果这些变化也你的解决方案的作品,谢谢!

相关问题