Golang实现验证码采集器的开发与实践
Golang实现验证码采集器的开发与实践 我正在寻找一位开发者帮我制作一个验证码绕过包。
我希望程序能打开一个窗口,允许用户登录他们的谷歌账户(保存会话以便用于验证码解决…登录谷歌有助于获得一键验证码,无需点击图片)。
该窗口将保持打开状态,直到我使用函数让窗口加载验证码。该函数将包含以下参数:siteUrl 和 siteKey(网站的验证码密钥)…打开的页面将显示验证码供用户解决。一旦验证码被解决,g-captcha-response 令牌应保存到字典中,包含网站 URL 和解决时间…然后验证码应重新加载,以便用户可以再次解决,新的响应令牌可以被存储。
这样字典将包含多个网站的多个令牌。 siteUrl => g-captcha-response 令牌 => 解决时间
这样我就可以获取该网站 URL 的所有令牌。
如果您能完成这个项目,请告知我,如果可能的话,我希望使用这个包:https://github.com/asticode/go-astilectron
我找到了一个类似的 GitHub 仓库,它是用 NodeJS 编写的,您可以将其作为基础参考。
dzt/captcha-harvester
协作式收集方法的可能计划 - dzt/captcha-harvester
更多关于Golang实现验证码采集器的开发与实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你好Alex,
我可以提供帮助:anna(dot)cis23(at)gmail(dot)com
谢谢!
Anna
更多关于Golang实现验证码采集器的开发与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
以下是使用 Go 语言结合 go-astilectron 库实现验证码采集器的示例代码。该代码创建一个 Electron 窗口,允许用户登录 Google 账户,然后加载指定 URL 和 siteKey 的验证码,并在解决后存储 g-captcha-response 令牌。
首先,确保安装必要的依赖:
go mod init captcha-harvester
go get github.com/asticode/go-astilectron
go get github.com/asticode/go-astilectron-bootstrap
然后,创建 main.go 文件:
package main
import (
"context"
"fmt"
"log"
"sync"
"time"
"github.com/asticode/go-astilectron"
bootstrap "github.com/asticode/go-astilectron-bootstrap"
)
// TokenStorage 存储验证码响应的结构
type TokenStorage struct {
sync.RWMutex
Tokens map[string][]TokenEntry
}
// TokenEntry 表示单个验证码响应条目
type TokenEntry struct {
ResponseToken string
SolvedAt time.Time
}
var storage = &TokenStorage{
Tokens: make(map[string][]TokenEntry),
}
// 添加令牌到存储
func (ts *TokenStorage) AddToken(siteURL, responseToken string) {
ts.Lock()
defer ts.Unlock()
entry := TokenEntry{
ResponseToken: responseToken,
SolvedAt: time.Now(),
}
ts.Tokens[siteURL] = append(ts.Tokens[siteURL], entry)
}
// 获取特定网站的所有令牌
func (ts *TokenStorage) GetTokens(siteURL string) []TokenEntry {
ts.RLock()
defer ts.RUnlock()
return ts.Tokens[siteURL]
}
// 加载验证码的函数
func LoadCaptcha(siteURL, siteKey string) error {
// 构建包含 reCAPTCHA 的 HTML 内容
htmlContent := fmt.Sprintf(`
<!DOCTYPE html>
<html>
<head>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
<div class="g-recaptcha" data-sitekey="%s" data-callback="onCaptchaSolved"></div>
<script>
function onCaptchaSolved(response) {
// 发送响应令牌回 Go 后端
if (window.astilectron) {
window.astilectron.sendMessage("captchaSolved", { siteUrl: "%s", responseToken: response });
}
}
</script>
</body>
</html>
`, siteKey, siteURL)
// 在现有窗口中加载 HTML
if err := bootstrap.SendMessage(astilectron.EventDispatchers{Proxifier: "window"}, "loadCaptcha", htmlContent, func(m *bootstrap.MessageIn) {
// 处理消息响应(如果需要)
}); err != nil {
return fmt.Errorf("发送加载验证码消息失败: %v", err)
}
return nil
}
// 处理消息的函数
func handleMessages(_ *astilectron.Window, m bootstrap.MessageIn) (payload interface{}, err error) {
switch m.Name {
case "captchaSolved":
// 解析消息负载
var data struct {
SiteURL string `json:"siteUrl"`
ResponseToken string `json:"responseToken"`
}
if err := m.Unmarshal(&data); err != nil {
log.Printf("解析 captchaSolved 消息失败: %v", err)
return nil, err
}
// 存储令牌
storage.AddToken(data.SiteURL, data.ResponseToken)
log.Printf("验证码已解决,站点: %s, 令牌: %s", data.SiteURL, data.ResponseToken)
// 可选:自动重新加载验证码以供再次解决
// 这里可以调用 LoadCaptcha 重新加载,但注意避免无限循环
}
return nil, nil
}
func main() {
// 使用 bootstrap 运行应用
if err := bootstrap.Run(bootstrap.Options{
AstilectronOptions: astilectron.Options{
AppName: "Captcha Harvester",
AppIconDefaultPath: "resources/icon.png", // 可选图标路径
AppIconDarwinPath: "resources/icon.icns", // macOS 图标
BaseDirectoryPath: ".",
},
Windows: []*bootstrap.Window{{
Homepage: "https://accounts.google.com", // 初始加载 Google 登录页面
MessageHandler: handleMessages,
Options: &astilectron.WindowOptions{
Center: astilectron.PtrBool(true),
Height: astilectron.PtrInt(700),
Width: astilectron.PtrInt(1200),
},
}},
OnWait: func(_ *astilectron.Astilectron, ws []*astilectron.Window, _ *astilectron.Menu, _ *astilectron.Tray, _ *astilectron.Menu) error {
// 应用启动后,窗口已打开,保持运行直到关闭
log.Println("应用已启动,窗口打开中...")
return nil
},
}); err != nil {
log.Fatalf("运行 bootstrap 失败: %v", err)
}
}
使用说明:
- 初始化窗口:应用启动时打开一个 Electron 窗口,加载 Google 登录页面(
https://accounts.google.com),用户可登录以简化验证码解决过程。 - 加载验证码:调用
LoadCaptcha函数(可通过其他机制触发,如 HTTP 端点或内部事件),传入siteUrl和siteKey。该函数动态生成包含 reCAPTCHA 的 HTML 并加载到窗口中。 - 处理验证码解决:当用户解决验证码时,JavaScript 回调
onCaptchaSolved被触发,通过astilectron发送消息到 Go 后端,存储g-captcha-response令牌到TokenStorage。 - 存储令牌:
TokenStorage使用映射结构,键为siteUrl,值为TokenEntry切片,每个条目包含响应令牌和解决时间。 - 获取令牌:通过
storage.GetTokens(siteURL)可检索特定网站的所有令牌。
示例调用 LoadCaptcha 函数:
在应用中,您可以通过事件或 API 触发验证码加载。例如,添加一个简单的 HTTP 服务器来接收请求:
import (
"net/http"
)
func main() {
// ... 上面的 bootstrap 代码 ...
// 启动 HTTP 服务器以触发验证码加载
http.HandleFunc("/load-captcha", func(w http.ResponseWriter, r *http.Request) {
siteURL := r.URL.Query().Get("siteUrl")
siteKey := r.URL.Query().Get("siteKey")
if siteURL == "" || siteKey == "" {
http.Error(w, "缺少 siteUrl 或 siteKey 参数", http.StatusBadRequest)
return
}
if err := LoadCaptcha(siteURL, siteKey); err != nil {
http.Error(w, fmt.Sprintf("加载验证码失败: %v", err), http.StatusInternalServerError)
return
}
w.Write([]byte("验证码加载成功"))
})
log.Println("HTTP 服务器启动在 :8080")
go http.ListenAndServe(":8080", nil)
// 保持主线程运行
select {}
}
运行应用后,访问 http://localhost:8080/load-captcha?siteUrl=example.com&siteKey=your_site_key 可触发验证码加载。解决后,令牌被存储,可通过 storage.GetTokens("example.com") 访问。
此实现基于 go-astilectron,提供了跨平台桌面应用功能,并参考了 Node.js 版本的逻辑。确保处理错误和边缘情况,如窗口管理和消息传递。

