func (s Scraper) GetPartList(URL string) (*PartList, error) {
	if !MatchPCPPURL(URL) {
		return nil, errors.New("invalid PCPartPicker URL")
	}
	URL = ConvertListURL(URL)

	var partList PartList

	s.Collector.OnHTML(".partlist__wrapper", func(el *colly.HTMLElement) {
		parts := []PartListPart{}

		el.ForEach(".tr__product", func(i int, prod *colly.HTMLElement) {
			partVendor := Vendor{
				InStock: false,
				Price:   Price{},
			}

			for k, v := range partListClassMappings {
				toParse := prod.ChildText(v)

				if strings.HasSuffix(toParse, "No Prices Available") || toParse == "FREE" {
					continue
				}
				stringPrice := strings.Replace(toParse, k, "", 1)
				price, curr, _ := StringPriceToFloat(stringPrice)

				switch k {
				case "Base":
					partVendor.Price.Base = price
				case "Promo":
					partVendor.Price.Discounts = price
				case "Shipping":
					partVendor.Price.Shipping = price
				case "Tax":
					partVendor.Price.Shipping = price
				case "Price":
					partVendor.Price.TotalString = strings.TrimSpace(stringPrice)
					partVendor.Price.Total = price
					partVendor.Price.Currency = curr
					partVendor.InStock = true
				}
			}

			if partVendor.InStock {
				partVendor.URL = linkURL("https://", el.Request.URL.Host, prod.ChildAttr(".td__where a", "href"))
				partVendor.Image = linkURL("https:", prod.ChildAttr(".td__where a img", "src"))
				partVendor.Name = ExtractVendorName(partVendor.URL)
			}

			part := PartListPart{
				Type:   prod.ChildText(".td__component"),
				Name:   prod.ChildText(".td__name"),
				Image:  linkURL("https:", prod.ChildAttr(".td__image a img", "src")),
				URL:    linkURL("https://", el.Request.URL.Host, prod.ChildAttr(".td__name a", "href")),
				Vendor: partVendor,
			}

			parts = append(parts, part)
		})

		listPrice := Price{}

		el.ForEach(".tr__total", func(i int, pr *colly.HTMLElement) {
			stringPrice := pr.ChildText(".td__price")
			val, curr, _ := StringPriceToFloat(stringPrice)

			switch pr.ChildText(".td__label") {
			case "Base Total:":
				listPrice.Base = val
			case "Tax:":
				listPrice.Tax = val
			case "Promo Discounts:":
				listPrice.Discounts = val
			case "Shipping:":
				listPrice.Shipping = val
			case "Total:":
				listPrice.Total = val
				listPrice.TotalString = stringPrice
				listPrice.Currency = curr
			}
		})

		compNotes := []CompNote{}

		el.ForEach("#compatibility_notes .info-message", func(i int, note *colly.HTMLElement) {
			mode := note.ChildText("span")
			compNotes = append(compNotes, CompNote{
				Message: strings.TrimLeft(strings.TrimSpace(note.Text), mode),
				Level:   strings.TrimRight(mode, ":"),
			})
		})

		partList = PartList{
			URL:           el.Request.URL.String(),
			Parts:         parts,
			Price:         listPrice,
			Wattage:       strings.TrimPrefix(el.ChildText(".partlist__keyMetric"), "Estimated Wattage:\n"),
			Compatibility: compNotes,
		}
	})
	err := s.Collector.Visit(URL)
	s.Collector.Wait()

	if err != nil {
		return nil, err
	}

	return &partList, nil
}
// Fetches data on a part list via URL.
Fetches data on a part list via URL.
// Fetches data on a part list via URL .
func (s Scraper) GetPartList(URL string) (*PartList, error) {
	if !MatchPCPPURL(URL) {
		return nil, errors.New("invalid PCPartPicker URL")
	}
	URL = ConvertListURL(URL)
	var partList PartList
	s.Collector.OnHTML(".partlist__wrapper", func(el *colly.HTMLElement) {
		parts := []PartListPart{}
		el.ForEach(".tr__product", func(i int, prod *colly.HTMLElement) {
			partVendor := Vendor{
				InStock: false,
				Price:   Price{},
			}
			for k, v := range partListClassMappings {
				toParse := prod.ChildText(v)
				if strings.HasSuffix(toParse, "No Prices Available") || toParse == "FREE" {
					continue
				}
				stringPrice := strings.Replace(toParse, k, "", 1)
				price, curr, _ := StringPriceToFloat(stringPrice)
				switch k {
				case "Base":
					partVendor.Price.Base = price
				case "Promo":
					partVendor.Price.Discounts = price
				case "Shipping":
					partVendor.Price.Shipping = price
				case "Tax":
					partVendor.Price.Shipping = price
				case "Price":
					partVendor.Price.TotalString = strings.TrimSpace(stringPrice)
					partVendor.Price.Total = price
					partVendor.Price.Currency = curr
					partVendor.InStock = true
				}
			}
			if partVendor.InStock {
				partVendor.URL = linkURL("https://", el.Request.URL.Host, prod.ChildAttr(".td__where a", "href"))
				partVendor.Image = linkURL("https:", prod.ChildAttr(".td__where a img", "src"))
				partVendor.Name = ExtractVendorName(partVendor.URL)
			}
			part := PartListPart{
				Type:   prod.ChildText(".td__component"),
				Name:   prod.ChildText(".td__name"),
				Image:  linkURL("https:", prod.ChildAttr(".td__image a img", "src")),
				URL:    linkURL("https://", el.Request.URL.Host, prod.ChildAttr(".td__name a", "href")),
				Vendor: partVendor,
			}
			parts = append(parts, part)
		})
		listPrice := Price{}
		el.ForEach(".tr__total", func(i int, pr *colly.HTMLElement) {
			stringPrice := pr.ChildText(".td__price")
			val, curr, _ := StringPriceToFloat(stringPrice)
			switch pr.ChildText(".td__label") {
			case "Base Total:":
				listPrice.Base = val
			case "Tax:":
				listPrice.Tax = val
			case "Promo Discounts:":
				listPrice.Discounts = val
			case "Shipping:":
				listPrice.Shipping = val
			case "Total:":
				listPrice.Total = val
				listPrice.TotalString = stringPrice
				listPrice.Currency = curr
			}
		})
		compNotes := []CompNote{}
		el.ForEach("#compatibility_notes .info-message", func(i int, note *colly.HTMLElement) {
			mode := note.ChildText("span")
			compNotes = append(compNotes, CompNote{
				Message: strings.TrimLeft(strings.TrimSpace(note.Text), mode),
				Level:   strings.TrimRight(mode, ":"),
			})
		})
		partList = PartList{
			URL:           el.Request.URL.String(),
			Parts:         parts,
			Price:         listPrice,
			Wattage:       strings.TrimPrefix(el.ChildText(".partlist__keyMetric"), "Estimated Wattage:\n"),
			Compatibility: compNotes,
		}
	})
	err := s.Collector.Visit(URL)
	s.Collector.Wait()
	if err != nil {
		return nil, err
	}
	return &partList, nil
}
func ( s Scraper ) GetPartList ( URL string ) ( * PartList , error ) { if ! MatchPCPPURL ( URL ) { return nil , errors . New ( " " ) } URL = ConvertListURL ( URL ) var partList PartList s . Collector . OnHTML ( " " , func ( el * colly . HTMLElement ) { parts := [ ] PartListPart { } el . ForEach ( " " , func ( i int , prod * colly . HTMLElement ) { partVendor := Vendor { InStock : false , Price : Price { } , } for k , v := range partListClassMappings { toParse := prod . ChildText ( v ) if strings . HasSuffix ( toParse , " " ) || toParse == " " { continue } stringPrice := strings . Replace ( toParse , k , " " , 1 ) price , curr , _ := StringPriceToFloat ( stringPrice ) switch k { case " " : partVendor . Price . Base = price case " " : partVendor . Price . Discounts = price case " " : partVendor . Price . Shipping = price case " " : partVendor . Price . Shipping = price case " " : partVendor . Price . TotalString = strings . TrimSpace ( stringPrice ) partVendor . Price . Total = price partVendor . Price . Currency = curr partVendor . InStock = true } } if partVendor . InStock { partVendor . URL = linkURL ( " " , el . Request . URL . Host , prod . ChildAttr ( " " , " " ) ) partVendor . Image = linkURL ( " " , prod . ChildAttr ( " " , " " ) ) partVendor . Name = ExtractVendorName ( partVendor . URL ) } part := PartListPart { Type : prod . ChildText ( " " ) , Name : prod . ChildText ( " " ) , Image : linkURL ( " " , prod . ChildAttr ( " " , " " ) ) , URL : linkURL ( " " , el . Request . URL . Host , prod . ChildAttr ( " " , " " ) ) , Vendor : partVendor , } parts = append ( parts , part ) } ) listPrice := Price { } el . ForEach ( " " , func ( i int , pr * colly . HTMLElement ) { stringPrice := pr . ChildText ( " " ) val , curr , _ := StringPriceToFloat ( stringPrice ) switch pr . ChildText ( " " ) { case " " : listPrice . Base = val case " " : listPrice . Tax = val case " " : listPrice . Discounts = val case " " : listPrice . Shipping = val case " " : listPrice . Total = val listPrice . TotalString = stringPrice listPrice . Currency = curr } } ) compNotes := [ ] CompNote { } el . ForEach ( " " , func ( i int , note * colly . HTMLElement ) { mode := note . ChildText ( " " ) compNotes = append ( compNotes , CompNote { Message : strings . TrimLeft ( strings . TrimSpace ( note . Text ) , mode ) , Level : strings . TrimRight ( mode , " " ) , } ) } ) partList = PartList { URL : el . Request . URL . String ( ) , Parts : parts , Price : listPrice , Wattage : strings . TrimPrefix ( el . ChildText ( " " ) , " \n " ) , Compatibility : compNotes , } } ) err := s . Collector . Visit ( URL ) s . Collector . Wait ( ) if err != nil { return nil , err } return & partList , nil }
Fetches data on a part list via URL.
Fetches data on a part list via URL .