我正在编写代码从 VK 下载视频,而不使用 VK API。任务如下:获取视频链接,然后向该 URL 发送请求并接收可观看该视频的页面作为响应。即模拟来自真实浏览器的请求。
为此,我尝试从真实的浏览器请求中复制所有标头,如下所示:
req, err := http.NewRequest("GET", URL, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 YaBrowser/24.7.0.0 Safari/537.36")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd")
req.Header.Set("Accept-Language", "ru,en;q=0.9")
req.Header.Set("Cache-Control", "max-age=0")
req.Header.Set("Sec-Ch-Ua", "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\", \"YaBrowser\";v=\"24.7\", \"Yowser\";v=\"2.5\"")
req.Header.Set("Sec-Ch-Ua-Mobile", "?0")
req.Header.Set("Sec-Ch-Ua-Platform", "\"macOS\"")
req.Header.Set("Sec-Fetch-Dest", "document")
req.Header.Set("Sec-Fetch-Mode", "navigate")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("Upgrade-Insecure-Requests", "1")
req.Header.Set("Priority", "u=0, I")
作为回应,我希望看到一个带有视频的页面以供进一步工作,但实际上我收到了一个页面,其中要求我更新/安装最新版本的浏览器。在 Pastebin 上收到的响应示例:URL。
问题是:如何在 Go 中模拟来自“现代”浏览器的请求?
完整的代码如下所示:
const URL = "https://m.vk.com/video-85466065_456241727"
req, err := http.NewRequest("GET", URL, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 YaBrowser/24.7.0.0 Safari/537.36")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd")
req.Header.Set("Accept-Language", "ru,en;q=0.9")
req.Header.Set("Cache-Control", "max-age=0")
req.Header.Set("Sec-Ch-Ua", "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\", \"YaBrowser\";v=\"24.7\", \"Yowser\";v=\"2.5\"")
req.Header.Set("Sec-Ch-Ua-Mobile", "?0")
req.Header.Set("Sec-Ch-Ua-Platform", "\"macOS\"")
req.Header.Set("Sec-Fetch-Dest", "document")
req.Header.Set("Sec-Fetch-Mode", "navigate")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("Upgrade-Insecure-Requests", "1")
req.Header.Set("Priority", "u=0, i")
client := &http.Client{}
res, err := client.Do(req)
在我看来,您从服务器得到了正确的响应。浏览器也会接收它,但它们执行 JS 脚本并重新加载页面。
证明:禁用 JS 的 chrome 截图
恕我直言,事情是这样的。服务器返回以下 cookie 集:
但是浏览器发送这些 cookie(cookie 的值不匹配,因为有些是在程序中接收的,有些是从浏览器接收的 - 比较名称集):
remixmdevice浏览器不是从 header接收 cookieSet-Cookie,而是从页面中的脚本接收 cookie。如果没有这个 cookie,服务器会显示一个“Bad Browser”页面,有了它就会显示一个正常页面我尝试用手添加这个饼干,结果成功了。这是我的标题集:
我不知道如何动态形成这个cookie。但目前它正在发挥作用。
附言。作为一个成年人,你当然应该使用 Selenium,但这真是一个魔鬼阿尔巴......