JS代理服务器请求Google数据遭拒,求解决实现方案
解决代理服务器请求Google被拒绝的问题
核心原因
你碰到的「www.google.com拒绝连接」是因为浏览器同源策略:前端JS不能直接跨域请求非同源的服务器资源,而Google的服务器也没有配置允许你的前端域名跨域访问的CORS规则,所以直接请求会被拦截。
代理服务器的核心逻辑是:用后端服务作为中间层,前端请求自己的后端,后端再去请求Google,最后把Google的响应返回给前端——绕过浏览器的同源限制。
实现步骤(用Node.js做后端,适配你的JS技术栈)
1. 搭建后端转发服务
先创建一个Node.js项目,安装依赖:
npm init -y npm install express cors axios
创建server.js,写转发逻辑:
const express = require('express'); const cors = require('cors'); const axios = require('axios'); const https = require('https'); const app = express(); const PORT = 3000; // 允许前端跨域请求 app.use(cors()); // 解析JSON请求体 app.use(express.json()); // 解析URL编码的请求体 app.use(express.urlencoded({ extended: true })); // 处理Google搜索/页面请求的转发接口 app.get('/proxy/google', async (req, res) => { try { // 获取前端传入的目标URL或搜索关键词 const { url, query } = req.query; let targetUrl; if (url) { // 如果是直接访问URL,直接转发 targetUrl = url.startsWith('http') ? url : `https://${url}`; } else if (query) { // 如果是搜索关键词,构造Google搜索URL targetUrl = `https://www.google.com/search?q=${encodeURIComponent(query)}`; } else { // 默认返回Google首页 targetUrl = 'https://www.google.com'; } // 发送请求到Google,转发请求头(模拟浏览器) const response = await axios.get(targetUrl, { headers: { 'User-Agent': req.headers['user-agent'] || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'Accept': req.headers['accept'] || 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': req.headers['accept-language'] || 'en-US,en;q=0.5', }, // 忽略SSL证书错误(如果遇到) httpsAgent: new https.Agent({ rejectUnauthorized: false }), // 允许重定向 maxRedirects: 5, }); // 把Google的响应返回给前端,包括状态码和响应头 res.status(response.status); // 过滤掉可能导致问题的响应头 const allowedHeaders = ['content-type', 'content-length', 'date', 'server']; Object.keys(response.headers).forEach(header => { if (allowedHeaders.includes(header.toLowerCase())) { res.setHeader(header, response.headers[header]); } }); res.send(response.data); } catch (error) { console.error('转发请求出错:', error.message); res.status(error.response?.status || 500).send('请求失败:' + error.message); } }); app.listen(PORT, () => { console.log(`代理后端运行在 http://localhost:${PORT}`); });
启动后端:
node server.js
2. 修改前端JS,添加搜索功能
更新你的index.js,给搜索按钮绑定点击事件,调用后端接口:
let tabCount = 1; function showTab(tabId) { const tabs = document.querySelectorAll('.tab-content'); tabs.forEach(tab => { tab.classList.remove('active'); }); document.getElementById(tabId).classList.add('active'); const tabElements = document.querySelectorAll('.tab'); tabElements.forEach(tab => { tab.classList.remove('active'); }); event.target.classList.add('active'); } function addNewTab() { tabCount++; const newTabId = `tab${tabCount}`; const newTab = document.createElement('div'); newTab.className = 'tab'; newTab.textContent = `Tab ${tabCount}`; newTab.setAttribute('onclick', `showTab('${newTabId}')`); document.querySelector('.add-tab').before(newTab); const newTabContent = document.createElement('div'); newTabContent.id = newTabId; newTabContent.className = 'tab-content'; newTabContent.innerHTML = ` <img src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png" alt="Google Logo" class="logo"> <div class="search-box"> <input type="text" id="${newTabId}-search-input" placeholder="Search Google or type a URL"> <button id="${newTabId}-search-btn" onclick="handleSearch('${newTabId}')">🔍</button> </div> <div class="buttons"> <button onclick="handleSearch('${newTabId}', true)">Google Search</button> <button onclick="handleLuckySearch('${newTabId}')">I'm Feeling Lucky</button> </div> <div id="${newTabId}-results" class="search-results"> <iframe id="${newTabId}-iframe" class="search-iframe" style="width: 100%; height: 80vh; display: none;" frameborder="0"></iframe> <div id="${newTabId}-html-content" style="display: none; text-align: left; padding: 20px;"></div> </div> `; document.body.appendChild(newTabContent); } // 给初始的Tab1添加事件监听 document.addEventListener('DOMContentLoaded', () => { // 绑定Tab1的搜索按钮 document.querySelector('#tab1 .search-box button').addEventListener('click', () => handleSearch('tab1')); document.querySelector('#tab1 .buttons button:first-child').addEventListener('click', () => handleSearch('tab1', true)); document.querySelector('#tab1 .buttons button:last-child').addEventListener('click', () => handleLuckySearch('tab1')); }); // 处理普通搜索 function handleSearch(tabId, isDirectSearch = false) { const input = document.getElementById(`${tabId}-search-input`); const query = input.value.trim(); if (!query) return; const resultsDiv = document.getElementById(`${tabId}-results`); const iframe = document.getElementById(`${tabId}-iframe`); const contentDiv = document.getElementById(`${tabId}-html-content`); // 隐藏之前的内容 iframe.style.display = 'none'; contentDiv.style.display = 'none'; let apiUrl; if (query.startsWith('http') || query.includes('.')) { // 如果是URL,直接转发 apiUrl = `http://localhost:3000/proxy/google?url=${encodeURIComponent(query)}`; // 用iframe加载(因为直接渲染HTML可能有资源路径问题) iframe.src = apiUrl; iframe.style.display = 'block'; } else { // 如果是搜索关键词 apiUrl = `http://localhost:3000/proxy/google?query=${encodeURIComponent(query)}`; if (isDirectSearch) { // 直接用iframe加载搜索结果页 iframe.src = apiUrl; iframe.style.display = 'block'; } else { // 或者获取HTML内容渲染到页面(可能需要处理资源路径) fetch(apiUrl) .then(res => res.text()) .then(html => { // 替换HTML中的绝对路径为代理路径(可选,解决图片、CSS加载问题) const proxiedHtml = html.replace(/https?:\/\/www\.google\.com/g, 'http://localhost:3000/proxy/google?url=https://www.google.com'); contentDiv.innerHTML = proxiedHtml; contentDiv.style.display = 'block'; }) .catch(err => { contentDiv.innerHTML = `<p>请求失败:${err.message}</p>`; contentDiv.style.display = 'block'; }); } } } // 处理"I'm Feeling Lucky" function handleLuckySearch(tabId) { const input = document.getElementById(`${tabId}-search-input`); const query = input.value.trim(); if (!query) return; const iframe = document.getElementById(`${tabId}-iframe`); // 构造Google的I'm Feeling Lucky URL const luckyUrl = `https://www.google.com/search?q=${encodeURIComponent(query)}&btnI`; // 通过代理转发 iframe.src = `http://localhost:3000/proxy/google?url=${encodeURIComponent(luckyUrl)}`; iframe.style.display = 'block'; }
关键注意事项
- CORS配置:后端必须开启CORS,否则前端还是会被浏览器拦截。
- 请求头模拟:必须转发浏览器的
User-Agent等请求头,否则Google会识别为非浏览器请求,拒绝返回内容或触发反爬。 - 资源路径处理:直接渲染Google的HTML时,里面的图片、CSS、JS路径是绝对路径,需要替换成通过你的代理后端访问的路径,否则这些资源会跨域加载失败(上面的代码里做了简单替换)。
- 反爬机制:Google有严格的反爬,频繁请求可能会被封IP,建议添加Cookie转发、请求间隔控制等,或者使用代理IP池(进阶内容)。
- HTTPS处理:如果要部署到线上,后端需要配置HTTPS,否则浏览器会阻止混合内容请求。
内容的提问来源于stack exchange,提问作者ermmmmm
相关产品推荐
相关产品推荐

