Golang解析需要登录的网站时遇到问题
Golang解析需要登录的网站时遇到问题 我正在尝试从供应商网站解析商品信息,但不知道为什么我的代码无法正常工作。我使用 MercuryEngineering/CookieMonster 设置 cookie,虽然能返回网站数据,但返回的是登录页面数据而不是商品页面数据:
func main() {
cookies, err := cookiemonster.ParseFile("MyCookieFile.txt")
if err != nil {
panic(err)
}
cookiejar, err := cookiejar.New(nil)
if err != nil {
panic(err)
}
u, err := url.Parse("MySite")
if err != nil {
panic(err)
}
cookiejar.SetCookies(u, cookies)
if err != nil {
panic(err)
}
// jujujar, err := cookiejar.New(&cookiejar.Options{
// Filename: cookies,
// })
// if err != nil {
// panic(err)
// }
client := &http.Client{
Jar: cookiejar,
}
response, err := client.Get("MySiteDirectoryWithProducts")
if err != nil {
panic(err)
}
query, err := goquery.NewDocumentFromResponse(response)
if err != nil {
panic(err)
}
myQuery := query.Find("body a").Each(func(index int, item *goquery.Selection) {
linkTag := item
link, _ := linkTag.Attr("href")
linkText := linkTag.Text()
fmt.Printf("Link #%d: '%s' - '%s'\n", index, linkText, link)
})
fmt.Print(myQuery)
}
更多关于Golang解析需要登录的网站时遇到问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
func main() {
fmt.Println("hello world")
}
更多关于Golang解析需要登录的网站时遇到问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
请确保 MyCookieFile.txt 中的 Cookie 是有效的。 你不能简单地复制浏览器中的 Cookie,因为它们通常在一段时间后会过期,并且是特定于你的浏览器的(服务器可能还会检查 User-Agent)。 要通过编程方式查询需要登录的网站,你也可以使用 Go 进行登录:将你的凭据发送到登录页面以获取新的 Cookie。
func main() {
fmt.Println("hello world")
}
问题在于你的代码没有正确处理会话管理和重定向。当网站需要登录时,仅仅设置Cookie可能不够,还需要确保会话有效且遵循正确的认证流程。
以下是修复后的代码:
package main
import (
"fmt"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"strings"
"time"
"github.com/PuerkitoBio/goquery"
cookiemonster "github.com/MercuryEngineering/CookieMonster"
)
func main() {
// 解析Cookie文件
cookies, err := cookiemonster.ParseFile("MyCookieFile.txt")
if err != nil {
log.Fatal("解析Cookie文件失败:", err)
}
// 创建Cookie Jar
jar, err := cookiejar.New(nil)
if err != nil {
log.Fatal("创建Cookie Jar失败:", err)
}
// 解析目标URL
targetURL := "MySite"
u, err := url.Parse(targetURL)
if err != nil {
log.Fatal("解析URL失败:", err)
}
// 设置Cookie到Jar
jar.SetCookies(u, cookies)
// 创建HTTP客户端,启用Cookie和重定向处理
client := &http.Client{
Jar: jar,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
// 在重定向时保持Cookie
return nil
},
Timeout: 30 * time.Second,
}
// 创建请求并设置必要的Header
req, err := http.NewRequest("GET", "MySiteDirectoryWithProducts", nil)
if err != nil {
log.Fatal("创建请求失败:", err)
}
// 设置用户代理和其他必要的Header
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
req.Header.Set("Accept-Language", "en-US,en;q=0.5")
req.Header.Set("Connection", "keep-alive")
// 发送请求
response, err := client.Do(req)
if err != nil {
log.Fatal("发送请求失败:", err)
}
defer response.Body.Close()
// 检查响应状态码
if response.StatusCode != http.StatusOK {
log.Printf("警告: 收到非200状态码: %d", response.StatusCode)
}
// 验证是否成功登录 - 检查响应内容是否包含登录页面特征
doc, err := goquery.NewDocumentFromReader(response.Body)
if err != nil {
log.Fatal("解析HTML失败:", err)
}
// 检查页面标题或特定元素来判断是否在登录页面
pageTitle := doc.Find("title").Text()
if strings.Contains(strings.ToLower(pageTitle), "login") ||
strings.Contains(strings.ToLower(pageTitle), "sign in") {
log.Fatal("仍然在登录页面,Cookie可能已过期或无效")
}
// 如果成功进入商品页面,提取链接
fmt.Println("成功访问商品页面,提取链接:")
doc.Find("body a").Each(func(index int, item *goquery.Selection) {
link, exists := item.Attr("href")
if exists {
linkText := item.Text()
fmt.Printf("Link #%d: '%s' - '%s'\n", index, strings.TrimSpace(linkText), link)
}
})
// 调试信息:显示当前Cookie
fmt.Printf("\n当前会话Cookie数量: %d\n", len(jar.Cookies(u)))
for i, cookie := range jar.Cookies(u) {
fmt.Printf("Cookie %d: %s=%s\n", i+1, cookie.Name, cookie.Value)
}
}
如果仍然遇到问题,可以添加会话验证功能:
// 验证会话是否有效
func validateSession(client *http.Client, baseURL string) bool {
req, err := http.NewRequest("GET", baseURL, nil)
if err != nil {
return false
}
resp, err := client.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
// 检查响应中是否包含登录相关的关键词
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return false
}
// 检查页面是否包含登录表单或登录相关文本
hasLoginForm := doc.Find("input[type='password']").Length() > 0
hasLoginText := strings.Contains(strings.ToLower(doc.Text()), "login") ||
strings.Contains(strings.ToLower(doc.Text()), "sign in")
return !hasLoginForm && !hasLoginText
}
主要修复点:
- 使用自定义请求而非简单的
client.Get(),以便设置必要的HTTP Header - 添加重定向处理确保Cookie在重定向过程中保持
- 添加会话验证逻辑检查是否成功登录
- 改进错误处理和调试信息输出
- 添加超时设置防止请求挂起

