Skip to content

Commit 939e679

Browse files
committed
feat: add GitHub proxy scraper and integrate into multi-scraper configuration
1 parent 2195084 commit 939e679

3 files changed

Lines changed: 129 additions & 1 deletion

File tree

internal/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ type ProxyConfig struct {
4141
type ScraperConfig struct {
4242
Timeout time.Duration `mapstructure:"timeout" validate:"required,min=5s,max=2m"`
4343
UserAgent string `mapstructure:"user_agent" validate:"required,min=10"`
44-
Sources []string `mapstructure:"sources" validate:"required,min=1,dive,oneof=proxyscrape freeproxylist geonode proxylistorg"`
44+
Sources []string `mapstructure:"sources" validate:"required,min=1,dive,oneof=proxyscrape freeproxylist geonode proxylistorg github"`
4545
}
4646

4747
type CheckerConfig struct {

pkg/scraper/github.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package scraper
2+
3+
import (
4+
"aproxy/internal/logger"
5+
"bufio"
6+
"context"
7+
"fmt"
8+
"io"
9+
"net/http"
10+
"strconv"
11+
"strings"
12+
"time"
13+
)
14+
15+
type GitHubProxyScraper struct {
16+
client *http.Client
17+
userAgent string
18+
logger *logger.Logger
19+
}
20+
21+
func NewGitHubProxyScraper() *GitHubProxyScraper {
22+
return &GitHubProxyScraper{
23+
client: &http.Client{
24+
Timeout: 30 * time.Second,
25+
},
26+
userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
27+
logger: logger.New("github"),
28+
}
29+
}
30+
31+
func NewGitHubProxyScraperWithConfig(config ScraperConfig) *GitHubProxyScraper {
32+
return &GitHubProxyScraper{
33+
client: &http.Client{
34+
Timeout: config.Timeout,
35+
},
36+
userAgent: config.UserAgent,
37+
logger: logger.New("github"),
38+
}
39+
}
40+
41+
func (g *GitHubProxyScraper) Name() string {
42+
return "github"
43+
}
44+
45+
func (g *GitHubProxyScraper) Scrape(ctx context.Context) ([]Proxy, error) {
46+
url := "https://raw.githubusercontent.com/proxifly/free-proxy-list/refs/heads/main/proxies/all/data.txt"
47+
48+
proxies, err := g.scrapeTextURL(ctx, url)
49+
if err != nil {
50+
return nil, fmt.Errorf("GitHub proxy scrape failed: %w", err)
51+
}
52+
53+
httpCount := 0
54+
for _, proxy := range proxies {
55+
if proxy.Type == "http" || proxy.Type == "https" {
56+
httpCount++
57+
}
58+
}
59+
60+
g.logger.InfoBg("GitHub collected: %d HTTP/HTTPS proxies", httpCount)
61+
return proxies, nil
62+
}
63+
64+
func (g *GitHubProxyScraper) scrapeTextURL(ctx context.Context, url string) ([]Proxy, error) {
65+
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
66+
if err != nil {
67+
return nil, err
68+
}
69+
70+
req.Header.Set("User-Agent", g.userAgent)
71+
72+
resp, err := g.client.Do(req)
73+
if err != nil {
74+
return nil, err
75+
}
76+
defer resp.Body.Close()
77+
78+
if resp.StatusCode != http.StatusOK {
79+
return nil, fmt.Errorf("HTTP %d", resp.StatusCode)
80+
}
81+
82+
return g.parseProtocolProxies(resp.Body)
83+
}
84+
85+
func (g *GitHubProxyScraper) parseProtocolProxies(reader io.Reader) ([]Proxy, error) {
86+
var proxies []Proxy
87+
scanner := bufio.NewScanner(reader)
88+
89+
for scanner.Scan() {
90+
line := strings.TrimSpace(scanner.Text())
91+
if line == "" {
92+
continue
93+
}
94+
95+
parts := strings.Split(line, "://")
96+
if len(parts) != 2 {
97+
continue
98+
}
99+
100+
protocol := parts[0]
101+
hostPort := parts[1]
102+
103+
hostPortParts := strings.Split(hostPort, ":")
104+
if len(hostPortParts) != 2 {
105+
continue
106+
}
107+
108+
port, err := strconv.Atoi(hostPortParts[1])
109+
if err != nil {
110+
continue
111+
}
112+
113+
proxy := Proxy{
114+
Host: hostPortParts[0],
115+
Port: port,
116+
Type: protocol,
117+
LastSeen: time.Now(),
118+
}
119+
120+
proxies = append(proxies, proxy)
121+
}
122+
123+
return proxies, scanner.Err()
124+
}

pkg/scraper/scraper.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ func NewMultiScraper() *MultiScraper {
1616
NewProxyScrapeAPI(),
1717
NewFreeProxyListScraper(),
1818
NewGeonodeAPIScraper(),
19+
NewGitHubProxyScraper(),
1920
},
2021
logger: logger.New("multiscraper"),
2122
}
@@ -34,6 +35,8 @@ func NewMultiScraperWithConfig(config ScraperConfig) *MultiScraper {
3435
scrapers = append(scrapers, NewGeonodeAPIScraperWithConfig(config))
3536
case "proxylistorg":
3637
scrapers = append(scrapers, NewProxyListOrgScraperWithConfig(config))
38+
case "github":
39+
scrapers = append(scrapers, NewGitHubProxyScraperWithConfig(config))
3740
}
3841
}
3942

@@ -42,6 +45,7 @@ func NewMultiScraperWithConfig(config ScraperConfig) *MultiScraper {
4245
NewProxyScrapeAPIWithConfig(config),
4346
NewFreeProxyListScraperWithConfig(config),
4447
NewGeonodeAPIScraperWithConfig(config),
48+
NewGitHubProxyScraperWithConfig(config),
4549
}
4650
}
4751

0 commit comments

Comments
 (0)