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

如何解决000webhost上PHP天气爬虫的SSL证书验证错误?

PHP天气爬虫部署到000webhost后SSL证书验证失败问题

问题详情

本地运行正常的PHP天气爬虫,部署到000webhost(站点:https://overprotective-gard.000webhostapp.com/?city=china)后出现以下SSL相关错误:

Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /storage/ssd4/367/20650367/public_html/index.php on line 17
Warning: file_get_contents(): Failed to enable crypto in /storage/ssd4/367/20650367/public_html/index.php on line 17
Warning: file_get_contents(https://www.weather-forecast.com/locations/london/forecasts/latest): failed to open stream: operation failed in /storage/ssd4/367/20650367/public_html/index.php on line 17

原代码如下:

<?php

$weather = "";
$error = "";
// if($_GET["city"]){ 
    // better way -->
    if(array_key_exists('city',$_GET))
    {
    $city = str_replace(' ','',$_GET['city']);

    $file_headers = @get_headers("https://www.weather-forecast.com/locations/".$city."/forecasts/latest");

    if($file_headers[0] == 'HTTP/1.1 404 Not Found'){
        $error = "City couldn't be found";
    }
    else{
    $forcastPage = file_get_contents("https://www.weather-forecast.com/locations/".$city."/forecasts/latest");
    
    $pageArray = explode('3 days)</div><p class="b-forecast__table-description-content"><span class="phrase">',$forcastPage);

    if(sizeof($pageArray) >1){
    $secondPageArray = explode('</span></p></td>',$pageArray[1]);
    if(sizeof($secondPageArray)>1){
    $weather =  $secondPageArray[0];
    }
    else{
        $error = "City couldn't be found";
    }
    }
    else{
        $error = "City couldn't be found";
    }
}

    }

?>

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Weather Scraper</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
    <style>
        html{
            background: url(sunset.avif) no-repeat center center fixed;
            background-size: cover;
        }
        body{
            background:none;
        }
        .container{
            text-align:center;
            margin-top: 100px;
            width:450px;
        }
        input{
            margin:20px 0;
        }
        #weather{
            margin-top: 15px;
        }
    </style>
</head>
  <body>
    <div class="container">
        <h1>What's the weather?</h1>
        <form>
  <div class="mb-3">
    <label for="city" class="form-label">Enter the name of a city</label>
    <input type="text" name="city" class="form-control" id="city" placeholder="Eg. London , Tokyo" 
    value = "<?php
    if(array_key_exists('city',$_GET))
    {
     echo $_GET["city"];
    }
     ?>">
    
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form> 
<div id="weather">
    <?php 
    if($weather){
        echo '<div class="alert alert-success" role="alert">
        '.$weather.'
      </div>';
    }
    else if($error){
        echo '<div class="alert alert-danger" role="alert">
        '.$error.'
      </div>';
    }
    ?>
</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
  </body>
</html>

错误原因

000webhost服务器上的PHP环境缺少可信根证书,导致file_get_contents和get_headers在请求HTTPS站点时无法验证目标服务器的SSL证书,从而触发SSL操作失败。

解决方案

替换file_get_contents和get_headers为cURL请求,手动禁用SSL证书验证(仅适用于此类爬虫场景,生产环境不推荐),同时优化错误处理逻辑。

修改后的完整代码

<?php

$weather = "";
$error = "";

if(array_key_exists('city',$_GET))
{
    $city = str_replace(' ','',$_GET['city']);
    $url = "https://www.weather-forecast.com/locations/".$city."/forecasts/latest";

    // 用cURL替代get_headers检查HTTP状态码
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if($httpCode == 404){
        $error = "City couldn't be found";
    }
    else{
        // 用cURL获取页面内容
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $forcastPage = curl_exec($ch);
        curl_close($ch);
        
        if($forcastPage === false){
            $error = "Failed to fetch weather data";
        } else {
            $pageArray = explode('3 days)</div><p class="b-forecast__table-description-content"><span class="phrase">',$forcastPage);

            if(sizeof($pageArray) >1){
                $secondPageArray = explode('</span></p></td>',$pageArray[1]);
                if(sizeof($secondPageArray)>1){
                    $weather =  $secondPageArray[0];
                }
                else{
                    $error = "City couldn't be found";
                }
            }
            else{
                $error = "City couldn't be found";
            }
        }
    }
}

?>

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Weather Scraper</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
    <style>
        html{
            background: url(sunset.avif) no-repeat center center fixed;
            background-size: cover;
        }
        body{
            background:none;
        }
        .container{
            text-align:center;
            margin-top: 100px;
            width:450px;
        }
        input{
            margin:20px 0;
        }
        #weather{
            margin-top: 15px;
        }
    </style>
</head>
  <body>
    <div class="container">
        <h1>What's the weather?</h1>
        <form>
  <div class="mb-3">
    <label for="city" class="form-label">Enter the name of a city</label>
    <input type="text" name="city" class="form-control" id="city" placeholder="Eg. London , Tokyo" 
    value = "<?php
    if(array_key_exists('city',$_GET))
    {
     echo htmlspecialchars($_GET["city"]);
    }
     ?>">
    
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form> 
<div id="weather">
    <?php 
    if($weather){
        echo '<div class="alert alert-success" role="alert">
        '.htmlspecialchars($weather).'
      </div>';
    }
    else if($error){
        echo '<div class="alert alert-danger" role="alert">
        '.htmlspecialchars($error).'
      </div>';
    }
    ?>
</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
  </body>
</html>

额外优化说明

  • 用cURL替代原生的file_get_contents和get_headers,通过CURLOPT_SSL_VERIFYHOST和CURLOPT_SSL_VERIFYPEER参数禁用SSL证书验证,解决服务器证书缺失问题。
  • 新增htmlspecialchars转义用户输入与输出内容,防范XSS攻击,提升代码安全性。
  • 添加cURL请求失败的判断逻辑,增强错误处理的全面性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 01:47:03