You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让社交平台分享跳转等待页时展示目标链接的Metadata?

实现跳转等待页分享时展示目标链接的Metadata

核心问题很明确:社交平台的分享爬虫(比如微信、Facebook、Twitter的爬虫)不会执行页面里的JavaScript,只会读取页面初始HTML中的<meta>标签。你现在用#哈希传递目标链接,依赖前端JS解析处理,但爬虫根本拿不到这个目标链接,更没法动态修改meta标签,所以只能显示等待页本身的空Metadata。

要解决这个问题,必须在服务器端处理请求,提前获取目标链接的Metadata并填充到页面的meta标签里,具体步骤如下:

1. 修改链接传参方式

把原来的#哈希传参改成查询参数,比如从your-wait-page.com#https://target-url.com改成your-wait-page.com?url=https://target-url.com。因为部分爬虫会忽略URL中的哈希部分,查询参数更稳定可靠。

2. 服务器端获取并填充Metadata

用服务器端代码(比如Node.js、PHP、Python等)接收请求,解析目标链接,然后抓取目标页面的Metadata,再动态渲染等待页的meta标签。

示例:Node.js/Express实现

假设你用Node.js搭建服务器,步骤如下:

  • 安装依赖:
npm install express axios cheerio
  • 编写服务器代码:
const express = require('express');
const axios = require('axios');
const cheerio = require('cheerio');
const app = express();

// 渲染等待页的模板函数
function renderWaitPage(targetMeta) {
  // 默认Metadata,当目标页无法获取时使用
  const defaultMeta = {
    title: '等待跳转...',
    description: '请稍等,即将为您跳转至目标页面',
    image: '你的默认图片URL'
  };
  const meta = {...defaultMeta, ...targetMeta};

  return `
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>${meta.title}</title>
    
  <meta property="og:title" content="${meta.title}" />
  <meta property="og:description" content="${meta.description}" />
  <meta property="og:image" content="${meta.image}" />
  <meta property="og:image:width" content="300" />
  <meta property="og:image:height" content="300" />
</head>
<body>
<!-- 原等待页HTML内容,仅修改JS的链接解析逻辑 -->
<div trbidi="on">
  <div style="padding: 0;">
    <div id="makingdifferenttimer" style="display: none;">
      <div id="notes_url" style="font-family: Electrolize,lolblogger,Tahoma; font-size: 16px; margin-top: 16px;">
        <div id="url_qu">
          .
        </div>
      </div>
    </div>
    <div id="mdtimer">
      <div style="font-family: Electrolize,lolblogger,Tahoma; text-align: center;">
        <b>Please wait...</b>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
        <!-- 原倒计时JS代码保持不变 -->
        <script type="text/javascript">
//<![CDATA[
!function(a,b,c,d){function g(b,c){this.element=b,this.settings=a.extend({},f,c),this.settings.fontSize||(this.settings.fontSize=this.settings.radius/1.2),this.settings.strokeWidth||(this.settings.strokeWidth=this.settings.radius/4),this._defaults=f,this._name=e,this._init()}var e="countdown360",f={radius:15.5,strokeStyle:"#2E64FE",strokeWidth:d,fillStyle:"#8ac575",fontColor:"#2E64FE",fontFamily:"Electrolize,lolblogger,Tahoma",fontSize:d,fontWeight:700,autostart:!0,seconds:20,label:["second","Seconds"],startOverAfterAdding:!0,onComplete:function(){}};g.prototype={getTimeRemaining:function(){var a=this._secondsLeft(this.getElapsedTime());return a},getElapsedTime:function(){return Math.round(((new Date).getTime()-this.startedAt.getTime())/1e3)},extendTimer:function(a){var b=parseInt(a),c=Math.round(((new Date).getTime()-this.startedAt.getTime())/1e3);this._secondsLeft(c)+b<=this.settings.seconds&&this.startedAt.setSeconds(this.startedAt.getSeconds()+parseInt(a))},addSeconds:function(a){var b=Math.round(((new Date).getTime()-this.startedAt.getTime())/1e3);this.settings.startOverAfterAdding?(this.settings.seconds=this._secondsLeft(b)+parseInt(a),this.start()):this.settings.seconds+=parseInt(a)},start:function(){this.startedAt=new Date,this._drawCountdownShape(3.5*Math.PI,!0),this._drawCountdownLabel(0),this.interval=setInterval(jQuery.proxy(this._draw,this),1e3)},stop:function(a){clearInterval(this.interval),a&&a()},_init:function(){this.settings.width=2*this.settings.radius+2*this.settings.strokeWidth,this.settings.height=this.settings.width,this.settings.arcX=this.settings.radius+this.settings.strokeWidth,this.settings.arcY=this.settings.arcX,this._initPen(this._getCanvas()),this.settings.autostart&&this.start()},_getCanvas:function(){var b=a('<canvas id="countdown360_'+a(this.element).attr("id")+'" width="'+this.settings.width+'" height="'+this.settings.height+'"><span id="countdown-text" role="status" aria-live="assertive"></span></canvas>');return a(this.element).prepend(b[0]),b[0]},_initPen:function(b){this.pen=b.getContext("2d"),this.pen.lineWidth=this.settings.strokeWidth,this.pen.strokeStyle=this.settings.strokeStyle,this.pen.fillStyle=this.settings.fillStyle,this.pen.textAlign="center",this.pen.textBaseline="middle",this.ariaText=a(b).children("#countdown-text"),this._clearRect()},_clearRect:function(){this.pen.clearRect(0,0,this.settings.width,this.settings.height)},_secondsLeft:function(a){return this.settings.seconds-a},_drawCountdownLabel:function(a){this.ariaText.text(b),this.pen.font=this.settings.fontWeight+" "+this.settings.fontSize+"px "+this.settings.fontFamily;var b=this._secondsLeft(a),c=1===b?this.settings.label[0]:this.settings.label[1],d=this.settings.label&&2===this.settings.label.length,e=this.settings.width/2;d?y=this.settings.height/2-this.settings.fontSize/6.2:y=this.settings.height/2,this.pen.fillStyle=this.settings.fillStyle,this.pen.fillText(b+1,e,y),this.pen.fillStyle=this.settings.fontColor,this.pen.fillText(b,e,y),d&&(this.pen.font="normal small-caps "+this.settings.fontSize/3+"px "+this.settings.fontFamily,this.pen.fillText(c,this.settings.width/2,this.settings.height/2+this.settings.fontSize/2.2))},_drawCountdownShape:function(a,b){this.pen.fillStyle=this.settings.fillStyle,this.pen.beginPath(),this.pen.arc(this.settings.arcX,this.settings.arcY,this.settings.radius,1.5*Math.PI,a,!1),this.pen.fill(),b&&this.pen.stroke()},_draw:function(){var a=Math.round(((new Date).getTime()-this.startedAt.getTime())/1e3),b=3.5*Math.PI-2*Math.PI/this.settings.seconds*a;this._clearRect(),this._drawCountdownShape(3.5*Math.PI,!1),a<this.settings.seconds?(this._drawCountdownShape(b,!0),this._drawCountdownLabel(a)):(this._drawCountdownLabel(this.settings.seconds),this.stop(),this.settings.onComplete())}},a.fn[e]=function(b){var c;return this.each(function(){c=a.data(this,"plugin_"+e),c||(c=new g(this,b),a.data(this,"plugin_"+e,c))}),c}}(jQuery,window,document);
//]]>
        </script>
        <br />
        <div class="time_dir" style="text-align: center;">
          <div id="container">
            <div id="countdown"></div>
            <script charset="utf-8" type="text/javascript">
var countdown=$("#countdown").countdown360({radius:90,seconds:3,fontColor:"#ffffff",strokeStyle:"#ff8000",fillStyle:"#ff4000",autostart:!1,onComplete:function(){console.log("done"),$(".download_faster").show(),$(".dowen_bum").show(),$("#container").remove()}});countdown.start();
            </script>
          </div>
        </div>
        <script type="text/javascript">
jQuery(document).ready(function(){var a=2;setInterval(function(){$("#mdtimer span").text(a--),0==a&&($("#makingdifferenttimer").delay(1e3).fadeIn(1e3),$("#mdtimer").hide(1e3).fadeOut('fast'))},1e3)});
$(document).ready(function(){
  // 修改:从查询参数获取目标链接,替代原hash解析逻辑
  var targetUrl = new URLSearchParams(window.location.search).get('url');
  $("#url_qu").html('<center><b>👇 Product link ready 👇🏻</b><br><br></center><a href="'+targetUrl+'" style="font-size: 18px;font-family:Electrolize,lolblogger,Tahoma;line-height: 35px;font-weight: 600;color: #FFFF;background:#0000ff;display: table;padding: 0px 61px 0 61px;margin: auto;box-shadow: 0px 1px 1px rgba(255,255,255,0.35) inset, 0px 1px 1px rgba(0,0,0,0.3);border-radius: 30px;" rel="nofollow"><i class="fa fa-arrow-down" aria-hidden="true"/>Click Here</a>');
  setTimeout(function(){window.location.href = targetUrl},11010);
});
        </script>
        <div><br /></div>
      </div>
    </div>
    <div style="text-align: center;"><center></center></div>
  </div>
</div>
</body>
</html>
  `;
}

// 处理等待页请求
app.get('/', async (req, res) => {
  const targetUrl = req.query.url;
  let targetMeta = {};

  if (targetUrl) {
    try {
      // 模拟爬虫UA,避免被目标网站拦截
      const response = await axios.get(targetUrl, {
        headers: {
          'User-Agent': 'Mozilla/5.0 (compatible; FacebookBot/1.0; +http://www.facebook.com/externalhit_uatext.php)'
        }
      });
      const $ = cheerio.load(response.data);

      // 提取目标页的og标签,没有则降级取普通meta或title
      targetMeta.title = $('meta[property="og:title"]').attr('content') || $('title').text();
      targetMeta.description = $('meta[property="og:description"]').attr('content') || $('meta[name="description"]').attr('content');
      targetMeta.image = $('meta[property="og:image"]').attr('content');
    } catch (err) {
      console.error('获取目标页Metadata失败:', err);
      // 失败则使用默认Metadata
    }
  }

  // 渲染页面并返回
  res.send(renderWaitPage(targetMeta));
});

app.listen(3000, () => {
  console.log('服务器运行在http://localhost:3000');
});

3. 关键注意事项

  • 爬虫UA模拟:目标网站可能会拦截非爬虫的请求,所以要设置User-Agent为社交平台爬虫的UA,比如FacebookBot、Twitterbot等。
  • 缓存机制:频繁请求目标页会被封,建议把提取到的Metadata缓存起来(比如用Redis),相同目标链接一段时间内直接用缓存内容。
  • 链接合法性验证:要校验目标链接是否合法,防止恶意链接或XSS攻击。
  • 静态页面限制:如果你的等待页是纯静态HTML(没有服务器端),那这个需求无法实现,因为客户端JS无法被爬虫识别,只能改用服务器端渲染方案。

内容的提问来源于stack exchange,提问作者ibrahim ramy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:40:28