You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过WordPress文章中插入的播客链接获取播客名称、剧集标题及日期(基于ACF插件)

Hey there! Great question—this is absolutely achievable with WordPress + ACF, and we can even make it AMP-compliant to match your needs. Here's a practical, step-by-step solution that mimics that WhatsApp-style link preview behavior:

Core Concept

We're building a link preview card that scrapes metadata from the podcast URL (using industry-standard tags like Open Graph and iTunes Podcast metadata) and stores/display it neatly. The key is to avoid real-time scraping on every page load (for performance) and ensure AMP compatibility.

First, add hidden ACF fields to store the scraped metadata (so we only scrape once, when the post is saved):

  • podcast_url (your existing URL field)
  • podcast_title (Text field: stores the podcast show name)
  • episode_title (Text field: stores the specific episode title)
  • podcast_date (Date field: stores the episode publish date)
  • podcast_cover (Text/Image field: stores the cover art URL)

Mark these fields as "Hidden" in ACF settings so editors don't manually edit them—we'll auto-populate them.

2. Build the Metadata Scraper Function

Create a PHP function to pull metadata from the podcast URL. We prioritize iTunes Podcast tags (since they're tailored for audio content) and fall back to Open Graph tags if needed:

function fetch_podcast_metadata($url) {
    $metadata = [];
    
    // Handle SSL verification (adjust for production if needed)
    $context = stream_context_create([
        'ssl' => ['verify_peer' => false, 'verify_peer_name' => false]
    ]);
    
    // Fetch the URL content
    $html = @file_get_contents($url, false, $context);
    if (!$html) return $metadata;

    // Parse HTML with DOMDocument
    $dom = new DOMDocument();
    libxml_use_internal_errors(true); // Suppress parsing warnings
    $dom->loadHTML($html);
    libxml_clear_errors();
    $xpath = new DOMXPath($dom);

    // Scrape iTunes and OG metadata
    $metadata['podcast_name'] = $xpath->query('//meta[@name="itunes:author"]/@content')->item(0)?->nodeValue ?? '';
    $metadata['episode_title'] = $xpath->query('//meta[@property="og:title"]/@content')->item(0)?->nodeValue ?? '';
    $metadata['publish_date'] = $xpath->query('//meta[@property="article:published_time"]/@content')->item(0)?->nodeValue ?? '';
    $metadata['cover_image'] = $xpath->query('//meta[@property="og:image"]/@content')->item(0)?->nodeValue ?? '';

    // Format date for WordPress compatibility
    if (!empty($metadata['publish_date'])) {
        $metadata['publish_date'] = date('Y-m-d', strtotime($metadata['publish_date']));
    }

    return $metadata;
}

3. Auto-Populate ACF Fields on Post Save

Use ACF's acf/save_post hook to automatically scrape and save metadata when the editor saves the post:

add_action('acf/save_post', 'auto_fill_podcast_metadata', 20);
function auto_fill_podcast_metadata($post_id) {
    // Skip autosaves/revisions
    if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) return;

    // Get the podcast URL from ACF
    $podcast_url = get_field('podcast_url', $post_id);
    if (empty($podcast_url)) return;

    // Scrape metadata
    $metadata = fetch_podcast_metadata($podcast_url);
    if (empty($metadata)) return;

    // Update ACF hidden fields
    update_field('podcast_title', $metadata['podcast_name'], $post_id);
    update_field('episode_title', $metadata['episode_title'], $post_id);
    update_field('podcast_date', $metadata['publish_date'], $post_id);
    update_field('podcast_cover', $metadata['cover_image'], $post_id);
}

4. Render the Preview Card (AMP-Compatible)

Regular WordPress Pages

Add this to your theme template (single.php, or a custom template part) to display the preview:

<div class="podcast-preview-card">
    <?php if ($cover = get_field('podcast_cover')): ?>
        <img src="<?php echo esc_url($cover); ?>" alt="<?php echo esc_attr(get_field('podcast_title')); ?>" class="podcast-cover">
    <?php endif; ?>
    <div class="podcast-info">
        <p class="podcast-show-name"><?php echo esc_html(get_field('podcast_title')); ?></p>
        <h4 class="podcast-episode-title"><?php echo esc_html(get_field('episode_title')); ?></h4>
        <p class="podcast-publish-date">Published: <?php echo esc_html(date('F j, Y', strtotime(get_field('podcast_date')))); ?></p>
        <a href="<?php echo esc_url(get_field('podcast_url')); ?>" target="_blank" rel="noopener noreferrer">Listen Now</a>
    </div>
</div>

AMP-Adjusted Rendering

AMP has strict rules, so modify the code to use AMP-compliant elements:

<div class="podcast-preview-card">
    <?php if ($cover = get_field('podcast_cover')): ?>
        <amp-img src="<?php echo esc_url($cover); ?>" 
                 alt="<?php echo esc_attr(get_field('podcast_title')); ?>"
                 width="150" 
                 height="150"
                 layout="fixed">
        </amp-img>
    <?php endif; ?>
    <div class="podcast-info">
        <p class="podcast-show-name"><?php echo esc_html(get_field('podcast_title')); ?></p>
        <h4 class="podcast-episode-title"><?php echo esc_html(get_field('episode_title')); ?></h4>
        <p class="podcast-publish-date">Published: <?php echo esc_html(date('F j, Y', strtotime(get_field('podcast_date')))); ?></p>
        <a href="<?php echo esc_url(get_field('podcast_url')); ?>" rel="noopener noreferrer">Listen Now</a>
    </div>
</div>
  • Replace <img> with <amp-img> (required for AMP)
  • Specify fixed width/height or use a responsive layout like responsive
  • Avoid target="_blank" if you're using AMP's strict mode, or keep it with rel="noopener noreferrer"

5. Optional: Real-Time Preview in the Editor

If you want editors to see the preview while typing, add a small JS snippet via ACF's admin hooks:

acf.add_action('change', function(field) {
    // Replace with your podcast URL field's ACF key
    if (field.key !== 'field_1234567890') return;

    const url = field.val();
    if (!url) return;

    // Use WordPress REST API to proxy the scrape (avoids CORS issues)
    fetch(`/wp-json/custom/v1/fetch-podcast-meta?url=${encodeURIComponent(url)}`)
        .then(res => res.json())
        .then(data => {
            const previewEl = document.querySelector('.podcast-editor-preview');
            if (!previewEl) return;

            previewEl.innerHTML = `
                <img src="${data.cover_image || ''}" alt="${data.podcast_name || ''}" style="max-width:150px;">
                <h3>${data.podcast_name || 'Unknown Podcast'}</h3>
                <h4>${data.episode_title || 'Unknown Episode'}</h4>
                <p>${data.publish_date ? new Date(data.publish_date).toLocaleDateString() : 'No Date'}</p>
            `;
        });
});

Then register the REST API endpoint to handle the request:

add_action('rest_api_init', function() {
    register_rest_route('custom/v1', '/fetch-podcast-meta', [
        'methods' => WP_REST_Server::READABLE,
        'callback' => 'fetch_podcast_metadata_rest',
        'permission_callback' => function() {
            return current_user_can('edit_posts');
        }
    ]);
});

function fetch_podcast_metadata_rest($request) {
    $url = $request->get_param('url');
    if (empty($url)) {
        return new WP_Error('missing_url', 'Please provide a podcast URL', ['status' => 400]);
    }
    $metadata = fetch_podcast_metadata($url);
    return rest_ensure_response($metadata);
}

Key Notes

  • Performance: By storing metadata in ACF fields, we avoid scraping the URL on every page load—this is critical for fast load times, especially on AMP pages.
  • Error Handling: Add fallback content (like a default cover image) if scraping fails or metadata is missing.
  • Security: Sanitize all scraped data with esc_url(), esc_html(), etc., to prevent XSS attacks.
  • AMP Compliance: Always test your AMP pages with the AMP Validator to ensure no violations.

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

火山引擎 最新活动