Advertisement
MatrixDeity

Untitled

Apr 22nd, 2023 (edited)
430
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 2.24 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "fmt"
  5.     "net/http"
  6.     "os"
  7.     "time"
  8. )
  9.  
  10. const (
  11.     bufferSize int = 128
  12. )
  13.  
  14. type Requester struct {
  15.     client    *http.Client
  16.     poolSize  int
  17.     buffer    []string
  18.     bufferIdx int
  19.     attempts  int
  20. }
  21.  
  22. type RequesterConfig struct {
  23.     PoolSize int
  24.     Timeout  time.Duration
  25.     Attempts int
  26. }
  27.  
  28. func New(config RequesterConfig) *Requester {
  29.     requester := &Requester{
  30.         client: &http.Client{
  31.             Timeout: config.Timeout,
  32.         },
  33.         poolSize:  config.PoolSize,
  34.         buffer:    make([]string, bufferSize),
  35.         bufferIdx: 0,
  36.         attempts:  config.Attempts,
  37.     }
  38.  
  39.     return requester
  40. }
  41.  
  42. func (r *Requester) Request(urls []string, filename string) {
  43.     outChan := make(chan string, len(urls))
  44.     defer close(outChan)
  45.  
  46.     r.asyncGet(urls, outChan)
  47.  
  48.     os.Remove(filename)
  49.     for i := 0; i < len(urls); i++ {
  50.         if r.bufferIdx == bufferSize {
  51.             r.dumpToFile(filename)
  52.         }
  53.  
  54.         resp := <-outChan
  55.         r.buffer[r.bufferIdx] = resp
  56.         r.bufferIdx++
  57.     }
  58.  
  59.     r.dumpToFile(filename)
  60. }
  61.  
  62. func (r *Requester) asyncGet(urls []string, outChan chan<- string) {
  63.     inChan := make(chan string, len(urls))
  64.     for _, url := range urls {
  65.         inChan <- url
  66.     }
  67.     close(inChan)
  68.  
  69.     for i := 0; i < r.poolSize; i++ {
  70.         go r.worker(inChan, outChan)
  71.     }
  72. }
  73.  
  74. func (r *Requester) worker(inChan <-chan string, outChan chan<- string) {
  75.     for url := range inChan {
  76.         for i := 1; i <= r.attempts; i++ {
  77.             response, err := r.client.Get(url)
  78.             if err == nil {
  79.                 defer response.Body.Close()
  80.                 outChan <- fmt.Sprintf("%s %d\n", url, response.StatusCode)
  81.  
  82.                 if response.StatusCode < 500 {
  83.                     break
  84.                 }
  85.             }
  86.         }
  87.     }
  88. }
  89.  
  90. func (r *Requester) dumpToFile(filename string) {
  91.     outfile, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
  92.     if err != nil {
  93.         panic(err)
  94.     }
  95.  
  96.     defer outfile.Close()
  97.  
  98.     for i := 0; i < r.bufferIdx; i++ {
  99.         outfile.WriteString(r.buffer[i])
  100.     }
  101.  
  102.     r.bufferIdx = 0
  103. }
  104.  
  105. func main() {
  106.     sites := []string{
  107.         "https://www.avito.ru/",
  108.         "https://www.ozon.ru/",
  109.         "https://vk.com/",
  110.         "https://yandex.ru/",
  111.         "https://www.google.com/",
  112.         "https://mail.ru/",
  113.         "https://ok.ru/",
  114.     }
  115.  
  116.     requester := New(RequesterConfig{
  117.         PoolSize: 32,
  118.         Timeout:  2 * time.Second,
  119.         Attempts: 3,
  120.     })
  121.     requester.Request(sites, "./out.txt")
  122. }
  123.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement