'Go Colly parallelism decreases the number of links scraped

I am trying to build a web scrapper to scrape jobs from internshala.com. I am using go colly to build the web scrapper. I visit every page and then visit the subsequent links of each job to scrape data from. Doing this in a sequential manner scrapes almost all the links, but if I try doing it by using colly's parallel scrapping the number of links scraped decreases. I write all the data in a csv file.

EDIT My question is why does this happen while scrapping parallelly and how can I solve it (how can I scrape all the data even when scrapping parallelly ). Or is there something else I am doing wrong that is cauing the problem. A code review will be really helpful. Thanks :)

package main

import (
    "encoding/csv"
    "log"
    "os"
    "strconv"
    "sync"
    "time"

    "github.com/gocolly/colly"
)


func main(){

        parallel(10)
        seq(10)
}

I comment out one of the two functions before running for obvious reasons.

parallel function :=


func parallel(n int){
    start := time.Now()
    c := colly.NewCollector(
        colly.AllowedDomains("internshala.com", "https://internshala.com/internship/detail", 
        "https://internshala.com/internship/", "internshala.com/", "www.intershala.com"),
        colly.Async(true),
    )

    d := colly.NewCollector(
        colly.AllowedDomains("internshala.com", "https://internshala.com/internship/detail", 
        "https://internshala.com/internship/", "internshala.com/", "www.intershala.com"),
        colly.Async(true),
    ) 

    
    c.Limit(&colly.LimitRule{DomainGlob: "*", Parallelism: 4})
    d.Limit(&colly.LimitRule{DomainGlob: "*", Parallelism: 4})

    fileName := "data.csv"
    file, err := os.Create(fileName)

    cnt := 0

    if err != nil{
        log.Fatalf("Could not create file, err: %q", err)
        return
    }

    defer file.Close() // close the file after the main routine exits

    writer := csv.NewWriter(file)
    defer writer.Flush()
    var wg sync.WaitGroup
    c.OnHTML("a[href]", func(e *colly.HTMLElement){

        if e.Attr("class") != "view_detail_button"{
            return
        }

        detailsLink := e.Attr("href")

        d.Visit(e.Request.AbsoluteURL(detailsLink))
        
    })
    
    d.OnHTML(".detail_view", func(e *colly.HTMLElement) {
        wg.Add(1)       

        go func(wg *sync.WaitGroup)  {
            writer.Write([]string{
                e.ChildText("span.profile_on_detail_page"),
                e.ChildText(".company_name a"),
                e.ChildText("#location_names a"),
                e.ChildText(".internship_other_details_container > div:first-of-type > div:last-of-type .item_body"),
                e.ChildText("span.stipend"),
                e.ChildText(".applications_message"),
                e.ChildText(".internship_details > div:nth-last-of-type(3)"),
                e.Request.URL.String(), 
            })
            wg.Done()
        }(&wg)
        

    })

    c.OnRequest(func(r *colly.Request) {
        
        log.Println("visiting", r.URL.String())
    })

    d.OnRequest(func(r *colly.Request) {
        
        log.Println("visiting", r.URL.String())
        cnt++
    })

    for i := 1; i < n; i++ {
        c.Visit("https://internshala.com/internships/page-"+strconv.Itoa(i))
    }

    c.Wait()
    d.Wait()
    wg.Wait()

    t := time.Since(start)

    log.Printf("time %v \n", t)
    log.Printf("amount %v \n", cnt)
    log.Printf("Scrapping complete")
    log.Println(c)

}

seq function :=

func seq(n int){
    start := time.Now()
    c := colly.NewCollector(
        colly.AllowedDomains("internshala.com", "https://internshala.com/internship/detail", 
        "https://internshala.com/internship/", "internshala.com/", "www.intershala.com"),
    )

    d := colly.NewCollector(
        colly.AllowedDomains("internshala.com", "https://internshala.com/internship/detail", 
        "https://internshala.com/internship/", "internshala.com/", "www.intershala.com"),
    ) 



    fileName := "data.csv"
    file, err := os.Create(fileName)

    cnt := 0

    if err != nil{
        log.Fatalf("Could not create file, err: %q", err)
        return
    }

    defer file.Close() // close the file after the main routine exits

    writer := csv.NewWriter(file)
    defer writer.Flush()

    c.OnHTML("a[href]", func(e *colly.HTMLElement){

        if e.Attr("class") != "view_detail_button"{
            return
        }

        detailsLink := e.Attr("href")

        d.Visit(e.Request.AbsoluteURL(detailsLink))
        
    })
    
    d.OnHTML(".detail_view", func(e *colly.HTMLElement) {
        
        
        writer.Write([]string{
            e.ChildText("span.profile_on_detail_page"),
            e.ChildText(".company_name a"),
            e.ChildText("#location_names a"),
            e.ChildText(".internship_other_details_container > div:first-of-type > div:last-of-type .item_body"),
            e.ChildText("span.stipend"),
            e.ChildText(".applications_message"),
            e.ChildText(".internship_details > div:nth-last-of-type(3)"),
            e.Request.URL.String(), 
        })
        

    })

    c.OnRequest(func(r *colly.Request) {
        
        log.Println("visiting", r.URL.String())
    })

    d.OnRequest(func(r *colly.Request) {
        
        log.Println("visiting", r.URL.String())
        cnt++
    })

    for i := 1; i < n; i++ {
        // Add URLs to the queue
        c.Visit("https://internshala.com/internships/page-"+strconv.Itoa(i))
    }

    t := time.Since(start)

    log.Printf("time %v \n", t)
    log.Printf("amount %v \n", cnt)
    log.Printf("Scrapping complete")
    log.Println(c)

}

Any help will be much appreciated. :)



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source