PHP实现通过公众号链接获取封面图

web前端 188 3个月前 (09-26)

微信中展示的封面图很小又无法下载,如何获取封面原图,闲来无事探究一下,发现公众号文章封面是文章html中“msg_cdn_url”变量的值,因此,用PHP实现的思路就有了。

首先写一个简单的HTML界面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>通过公众号文章链接获取封面图-拓源网</title>
</head>
<body>
    <div class="box">
        <h3>通过公众号文章链接获取封面图</h3>
        <form id="mpform" action="" method="post">
            <input type="text" name="url" placeholder="此处粘贴公众号文章链接" autocomplete="off" class="url">
            <button type="button" class="btn">获取封面图</button>
        </form>
        <?php if(isset($mpThumb)){echo '<div class="result"><em>提示:请右键另存为下载图片</em><img src="'.$dir.'temp.jpg"></div>';}?>
        <div class="tips">
            <dl>
                <dt></dt>
                <dd>在微信中打开公众号文章,点击右上角菜单中的“<code>复制链接</code>”,粘贴到上方文本框内,点击按钮获取封面图。</dd>
            </dl>
        </div>
    </div>
</body>
</html>

界面是否好看当然取决于CSS样式:

*,body { margin:0; padding:0; }
.box { width:750px; padding:24px; margin:20px auto 0; border:1px solid #eee; border-top-width:5px; border-radius:4px; box-sizing:border-box; background:#f8f8f8; }
.box h3 { font-size:18px; color:#333; font-weight:normal; text-align:center; }
.url { width:100%; height:50px; margin-top:20px; font-family:verdana,'Microsoft Yahei'; line-height:50px; padding:0 14px; font-size:16px; color:#333; border:1px solid #eee; border-radius:4px; box-sizing:border-box; background:#fff; }
.url.error, .url.error:focus { color:#f00; border-color:#f00; box-shadow:0 0 0 .2rem #ffdcdc; }
.url:focus { color:#2aae67; border-color:#2aae67; outline:0; box-shadow:0 0 0 .2rem #daf1e5; background:#fff; }
.btn { width:100%; height:50px; margin-top:20px; font-size:18px; color:#fff; border:0; border-radius:4px; cursor:pointer; background:#2aae67; }
.result { position:relative; }
.result em { padding:0 10px; font-size:12px; color:#fff; font-style:normal; line-height:24px; border-top-left-radius:4px; border-bottom-left-radius:4px; background:rgba(0,0,0,.5); position:absolute; top:6px; right:0; z-index:1; }
.result img { width:100%; margin-top:20px; border-radius:4px; display:block; }
.tips { margin-top:20px; font-size:14px; color:#999; }
.tips dt { margin-bottom:6px; padding-bottom:6px; font-size:14px; color:#333; font-weight:bold; border-bottom:1px solid #eee; }
.tips dd { font-size:12px; color:#666; line-height:1.8; }
.tips dd code { margin:0 4px; padding:0 4px; font-size:12px; line-height:1.5; border:1px solid #b0efcd; border-radius:4px; background:#daf1e5; display:inline-block; }
@media screen and (max-width:750px){
    .box { width:auto; margin:20px 10px 0; }
}

点击“获取封面图”按钮要判断文本框是否为空,以及粘贴公众号的链接格式是否正确,这些前端逻辑交由js来处理(提前引入jquery库):

$(function(){
    function urlStartsWith(url, startsWith) {
        return url.startsWith(startsWith);
    }
    $(".btn").click(function(){
        if($(".url").val() == ''){
            $(".url").focus();
            $(".url").addClass("error").attr('placeholder','公众号文章链接不能为空!');
            return false;
        }else if(!urlStartsWith($(".url").val(), 'https://mp.weixin.qq.com/s/')){
            $(".url").focus();
            $(".url").addClass("error").val('').attr('placeholder','公众号文章链接格式不正确!');
            return false;
        }else{
            $(".url").keydown(function(){
                $(this).removeClass("error").attr('placeholder','此处粘贴公众号文章链接');
            });
            $("#mpform").submit();
        }
    });
});

界面有了,接下来要用PHP实现接收表单传过来的公众号链接,进而使用正则表达式获取公众号html中变量msg_cdn_url的值,也就是封面图的地址,在html代码最上方插入:

<?php
if(isset($_POST['url'])){
    $url = htmlspecialchars($_POST['url']);
    $data = file_get_contents($url);
    preg_match_all('/var msg_cdn_url = "(.*?)";/',$data,$matches);
    $mpThumb = $matches[1][0];
}
?>

获取的封面图显示“此图片来自微信公众平台未经允许不可引用”,不支持外部调用,所以还需优化一下php代码将封面图片本地化:

<?php
//当前文件创建同级目录,名字mpThumbs自定义,
$dir = './mpThumbs/';
if (!is_dir($dir)) {
    mkdir($dir, 0777, true);
}

function downloadImage($remoteUrl, $localPath) {
    $ch = curl_init($remoteUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        $error_msg = curl_error($ch);
        curl_close($ch);
        throw new Exception("cURL Error: " . $error_msg);
    }
    curl_close($ch);
    if (!file_put_contents($localPath, $response)) {
        throw new Exception("Failed to save image to local file.");
    }
    return true;
}

if(isset($_POST['url'])){
    $url = htmlspecialchars($_POST['url']);
    $data = file_get_contents($url);
    preg_match_all('/var msg_cdn_url = "(.*?)";/',$data,$matches);
    $mpThumb = $matches[1][0];
    downloadImage($mpThumb, $dir.'temp.jpg');
}
?>

这样就在php文件同级创建了mpThumbs目录,用于保存下载的封面图,至此,一个获取微信公众号封面的功能就实现了,但题外之言,下载的图片未经权利人许可不能侵权使用。

》》》演示地址

分享给朋友: