Next.js/React应用中动态Open Graph元标签的组件实现及爬虫抓取问题求助
Next.js/React应用中动态Open Graph元标签的组件实现及爬虫抓取问题求助
我最近在Next.js/React项目里碰到了一个头疼的问题:动态生成的Open Graph(OG)元标签,在Chrome的Elements面板里明明能看到,但LinkedIn帖子检查器和Facebook调试工具就是抓不到。看Network面板的Response内容,里面根本没有这些OG标签,爬虫自然也就识别不了。
下面是我当前的代码实现,麻烦帮我看看哪里出问题了:
页面组件:src/pages/share-property/index.tsx
import React from "react"; import Property from "components/Sharing/Property"; import { GetServerSideProps } from "next"; import { Buffer } from 'buffer'; import { NextPage } from 'next'; import Head from 'next/head'; // Import Head interface PropertyData { companyName: string; tenantId: string; stage: string; firstName: string; imageUrl: string; headerText?: string; resolvedImageUrl: string; fullUrl: string; } interface Props { propertyData: PropertyData | null; } const IndexPage: NextPage<Props> = ({ propertyData }) => { const shareTitle = propertyData ? `${propertyData.companyName} - ${propertyData.headerText}` : 'Loading...'; const shareDescription = propertyData ? `Check out this property update from ${propertyData.companyName}` : ''; return ( <> <Head> {/* Primary Meta Tags */} <title>{shareTitle}</title> <meta name="description" content={shareDescription} /> <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" /> {propertyData && ( <> {/* Open Graph / Facebook */} <meta property="og:title" content={shareTitle} /> <meta property="og:description" content={shareDescription} /> <meta property="og:image" content={propertyData.resolvedImageUrl} /> <meta property="og:url" content={propertyData.fullUrl} /> <meta property="og:type" content="website" /> <meta property="og:image:width" content="1200" /> <meta property="og:image:height" content="630" /> <meta property="og:image:alt" content={`Property image from ${propertyData.companyName}`} /> <meta property="og:site_name" content={propertyData.companyName} /> {/* Twitter */} <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content={shareTitle} /> <meta name="twitter:description" content={shareDescription} /> <meta name="twitter:image" content={propertyData.resolvedImageUrl} /> </> )} </Head> {propertyData ? ( <Property companyName={propertyData.companyName} tenantId={propertyData.tenantId} stage={propertyData.stage} firstName={propertyData.firstName} imageUrl={propertyData.imageUrl} headerText={propertyData.headerText} resolvedImageUrl={propertyData.resolvedImageUrl} fullUrl={propertyData.fullUrl} /> ) : ( <div>Loading property data...</div> )} </> ); }; export const getServerSideProps: GetServerSideProps<Props> = async (context) => { const { query, req } = context; const data = query.data as string; console.log("getServerSideProps is running"); if (!data) { console.log("No data query parameter"); return { props: { propertyData: null }, }; } try { const decodedData = JSON.parse(Buffer.from(data, 'base64').toString('utf-8')); const { companyName, stage, imageUrl, firstName = "", tenantId = "", headerText = "Property Update" } = decodedData; const origin = req ? `${req.headers['x-forwarded-proto'] || 'http'}://${req.headers.host}` : ''; const fullUrl = `${origin}${context.resolvedUrl}`; const getAbsoluteImageUrlServerSide = (url: string) => { if (!url) return ''; if (url.startsWith('http')) return url; if (url.startsWith('//')) return `https:${url}`; return `${origin}${url.startsWith('/') ? '' : '/'}${url}`; }; const resolvedImageUrl = getAbsoluteImageUrlServerSide(imageUrl); console.log("Property Data:", { companyName, tenantId, stage, firstName, imageUrl, headerText, resolvedImageUrl, fullUrl, }); return { props: { propertyData: { companyName, tenantId, stage, firstName, imageUrl, headerText, resolvedImageUrl, fullUrl, }, }, }; } catch (error) { console.error('Error processing data in getServerSideProps:', error); return { props: { propertyData: null }, }; } }; export default IndexPage;
子组件:src/components/Sharing/Property.tsx
import React from 'react'; import { Box, Typography, Button, Card, CardMedia, CardContent } from '@mui/material'; import Link from 'next/link'; import Head from 'next/head'; import styles from 'styles/ShareButton.module.scss'; interface PropertyProps { companyName: string; tenantId: string; stage: string; firstName: string; imageUrl: string; headerText?: string; resolvedImageUrl: string; fullUrl: string; } const Property = ({ companyName, tenantId, stage, firstName, imageUrl, headerText = "Property Update", resolvedImageUrl, fullUrl }: PropertyProps) => { return ( <Box sx={{ maxWidth: 800, margin: '0 auto', padding: 3 }}> <Card elevation={3}> <CardMedia component="img" height="400" image={resolvedImageUrl} alt={`Property update from ${companyName}`} /> <CardContent> <Typography variant="h4" component="h1" gutterBottom> {headerText} </Typography> <Typography variant="body1" color="text.secondary" paragraph> Hi {firstName}, here's your latest property update from {companyName}. </Typography> <Typography variant="body1" paragraph> Current stage: {stage} </Typography> <Link href={fullUrl} passHref> <Button variant="contained" color="primary"> View Full Details </Button> </Link> </CardContent> </Card> </Box> ); }; export default Property;
我已经用了getServerSideProps来做服务端渲染,按道理爬虫请求的时候应该能拿到完整渲染后的HTML(包含OG标签),但实际Network的Response里就是没有这些标签。有没有大佬能帮我分析下问题出在哪?
内容来源于stack exchange
相关产品推荐
相关产品推荐

