Улучшена обработка метаданных ссылок
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m4s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m4s
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
@@ -12888,8 +12889,6 @@ func (a *App) extractLinkMetadataHandler(w http.ResponseWriter, r *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Extracting metadata for URL: %s", req.URL)
|
||||
|
||||
// Валидация URL
|
||||
parsedURL, err := url.Parse(req.URL)
|
||||
if err != nil || parsedURL.Scheme == "" || parsedURL.Host == "" {
|
||||
@@ -12925,20 +12924,41 @@ func (a *App) extractLinkMetadataHandler(w http.ResponseWriter, r *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
// Устанавливаем заголовки, имитирующие реальный браузер Chrome
|
||||
httpReq.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
|
||||
// Устанавливаем заголовки, максимально имитирующие реальный браузер Chrome
|
||||
// Актуальный User-Agent для Chrome на macOS
|
||||
httpReq.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36")
|
||||
|
||||
// Accept заголовки для максимальной совместимости
|
||||
httpReq.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")
|
||||
httpReq.Header.Set("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7")
|
||||
httpReq.Header.Set("Accept-Encoding", "gzip, deflate, br")
|
||||
httpReq.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd")
|
||||
|
||||
// Заголовки для имитации реального браузера
|
||||
httpReq.Header.Set("Connection", "keep-alive")
|
||||
httpReq.Header.Set("Upgrade-Insecure-Requests", "1")
|
||||
httpReq.Header.Set("Sec-Fetch-Dest", "document")
|
||||
httpReq.Header.Set("Sec-Fetch-Mode", "navigate")
|
||||
httpReq.Header.Set("Sec-Fetch-Site", "none")
|
||||
httpReq.Header.Set("Sec-Fetch-User", "?1")
|
||||
httpReq.Header.Set("Sec-Ch-Ua", `"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"`)
|
||||
httpReq.Header.Set("Sec-Ch-Ua-Mobile", "?0")
|
||||
httpReq.Header.Set("Sec-Ch-Ua-Platform", `"macOS"`)
|
||||
|
||||
// Дополнительные заголовки для лучшей совместимости
|
||||
httpReq.Header.Set("Cache-Control", "max-age=0")
|
||||
httpReq.Header.Set("DNT", "1")
|
||||
|
||||
// Устанавливаем Referer - для некоторых сайтов это важно для обхода защиты
|
||||
// Используем главную страницу домена как Referer, чтобы имитировать переход с главной
|
||||
if parsedURL.Host != "" {
|
||||
referer := fmt.Sprintf("%s://%s/", parsedURL.Scheme, parsedURL.Host)
|
||||
httpReq.Header.Set("Referer", referer)
|
||||
}
|
||||
|
||||
// Добавляем небольшую задержку перед запросом для имитации человеческого поведения
|
||||
// Это может помочь избежать триггера капчи при слишком быстрых запросах
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
resp, err := client.Do(httpReq)
|
||||
if err != nil {
|
||||
log.Printf("Error fetching URL %s: %v", req.URL, err)
|
||||
@@ -12947,9 +12967,6 @@ func (a *App) extractLinkMetadataHandler(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Логируем статус код для отладки
|
||||
log.Printf("Fetched URL %s, status: %d", req.URL, resp.StatusCode)
|
||||
|
||||
// Принимаем успешные статусы (200-299) и некоторые редиректы, которые могут содержать контент
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
// Для некоторых сайтов можно попробовать прочитать тело даже при не-200 статусе
|
||||
@@ -12960,6 +12977,8 @@ func (a *App) extractLinkMetadataHandler(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
// Ограничиваем размер ответа (первые 512KB)
|
||||
// ВАЖНО: Go's http.Client автоматически декодирует gzip, если заголовок Accept-Encoding установлен
|
||||
// Но нужно убедиться, что мы читаем декодированные данные
|
||||
limitedReader := io.LimitReader(resp.Body, 512*1024)
|
||||
bodyBytes, err := io.ReadAll(limitedReader)
|
||||
if err != nil {
|
||||
@@ -12968,6 +12987,20 @@ func (a *App) extractLinkMetadataHandler(w http.ResponseWriter, r *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
// Проверяем, является ли это gzip (магические байты: 1f 8b)
|
||||
// Go's http.Client должен автоматически декодировать gzip, но на всякий случай проверяем
|
||||
if len(bodyBytes) >= 2 && bodyBytes[0] == 0x1f && bodyBytes[1] == 0x8b {
|
||||
// Пытаемся декодировать вручную, если автоматическое декодирование не сработало
|
||||
gzipReader, err := gzip.NewReader(bytes.NewReader(bodyBytes))
|
||||
if err == nil {
|
||||
defer gzipReader.Close()
|
||||
decompressed, err := io.ReadAll(gzipReader)
|
||||
if err == nil {
|
||||
bodyBytes = decompressed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body := string(bodyBytes)
|
||||
metadata := &LinkMetadataResponse{}
|
||||
|
||||
@@ -13006,6 +13039,15 @@ func (a *App) extractLinkMetadataHandler(w http.ResponseWriter, r *http.Request)
|
||||
titleRe := regexp.MustCompile(`(?i)<title[^>]*>([^<]+)</title>`)
|
||||
if matches := titleRe.FindStringSubmatch(body); len(matches) > 1 {
|
||||
metadata.Title = strings.TrimSpace(matches[1])
|
||||
|
||||
// Проверяем, не попали ли мы на страницу капчи
|
||||
if strings.Contains(strings.ToLower(metadata.Title), "робот") ||
|
||||
strings.Contains(strings.ToLower(metadata.Title), "captcha") ||
|
||||
strings.Contains(strings.ToLower(metadata.Title), "вы не робот") {
|
||||
metadata.Title = ""
|
||||
metadata.Image = ""
|
||||
metadata.Description = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "play-life-web",
|
||||
"version": "3.26.1",
|
||||
"version": "3.26.2",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
Reference in New Issue
Block a user