PHP

hanhanjun888@163.com

个人技术分享

php操作cookie 转换数组形式,可取某一个值
if (!function_exists('ckStr2ckArr')) {
    function ckStr2ckArr($cookieValue,$key='')
    {
        if(empty($cookieValue)) return [];
        // 第一步:将 cookie 字符串拆分为键值对数组
        $cookiePairs = explode(';', $cookieValue);
        // 创建一个关联数组来存储键值对
        $cookieArray = [];
        foreach ($cookiePairs as $pair) {
            $pair = trim($pair); // 去除多余的空格
            if ($pair) {
                list($k, $value) = explode('=', $pair, 2);
                $cookieArray[$k] = $value;
            }
        }
        //取指定的key值
        if(!empty($key)) return $cookieArray[$key];
        //取所有数组
        return $cookieArray;
    }
}
$str = 'cna=Z10vHxyLLhkCAXPgqFaTMN9A; t=0dfd9e12691b5e686d8e406981bc179f; cookie2=113f243906b3776465e8fc246291d43d; xlly_s=1; _samesite_flag_=true; _tb_token_=548dd75bd1b39; unb=2209368547703; _hvn_lgc_=77; mtop_partitioned_detect=1; _m_h5_tk=518ab9b7ade30d1634c92f423962eb36_1729138819303; _m_h5_tk_enc=548aa63b41127caaeb4e9bc65e796a49; sdkSilent=1729216940928; sgcookie=E100MANykuWklerydA%2BMl9VIKBDu93fi6%2FAkc52GgwunEqZm9s%2F4QR3w70efJdK0OjoqaSSsURjd8rmp0UbOxRuxqtfyCuinoz28cswnbcjUUfk%3D; csg=96db0be1; havana_lgc2_77=eyJoaWQiOjIyMDkzNjg1NDc3MDMsInNnIjoiM2I1OTA0MDEzYTljZTcwZTRkZDkwYTQ1YzkzYjgxYzEiLCJzaXRlIjo3NywidG9rZW4iOiIxcEprcmNFY3FXa3l3U1RnY2hhT1U0dyJ9; havana_lgc_exp=1731722711974; isg=BHd3EOiN3F5lmFlq1jMGY7UyBm3BPEuetKiDGckl5cateJK60QzK7iOTWtgmkCMW; tfstk=gtErVp23SDVj2CSshxnEQC-n2_n-D0f1tkGIKJ2nFbcoAahntJFxdHw3VWPU_7-7OJf8TklmM2aWVWNeT7NjZ3wSNSl31SZI-6n7gSa0k_C-O8MUGr4Aw_EUpHk3KWB-OTQbe8nKx11_YGw8eWEySDXjrIXnLv1_7crXm8nKx19XxNsae50nOCBExtomdYJox2cl3jDsi3DHqvAc3vhmx30nrqAmevkk-vV3ntkKiXDL382H0AglCB0NDGfWA4cgEj-HbdHrrewWRh-a0Yuzx8cVL9rqU4lilG5xelygElHUvOYETzzuNxFFbso0gy2nuo1kfXaaCk3Uq9pS9zMtqYPhjFG0u-q-5-pPI-ija-DTu1--VRz0VqEGG3FUC7rE57scEWnoKW3TA1K-ZJ2TXPiNYFogg-qt-kCvvXabKko8sst492jrHBHmRXqLzBYnrxHq1tW4O4UiIC35k2YpJqmt3f6SFeLKrWMq1TgBJe3mtxl1Fw5..';
//转换数组
$arr = ckStr2ckArr($newStr);
dump($arr);
//取数组中某一个值
$arr = ckStr2ckArr($newStr,'cookie2');
dump($arr);die;
hanhanjun888@163.com

个人技术分享

php操作cookie字符串,替换对应值
  • 将原始字符串中的unb和cookie2的值替换
if (!function_exists('ckStrReplace')) {
    function ckStrReplace($cookieValue,$replacements)
    {
        if(empty($cookieValue)) return '';
        if(empty($replacements) || !is_array($replacements)) return '';
        // 第一步:将 cookie 字符串拆分为键值对数组
        $cookiePairs = explode(';', $cookieValue);

        // 创建一个关联数组来存储键值对
        $cookieArray = [];
        foreach ($cookiePairs as $pair) {
            $pair = trim($pair); // 去除多余的空格
            if ($pair) {
                list($key, $value) = explode('=', $pair, 2);
                $cookieArray[$key] = $value;
            }
        }

        // 第二步:根据 replacements 数组更新或者添加相应的值
        foreach ($replacements as $key => $newValue) {
            // 如果数组中有这个键,进行替换
            $cookieArray[$key] = $newValue;
        }

        // 第三步:重新组装成 cookie 字符串
        $newCookieValue = '';
        foreach ($cookieArray as $key => $value) {
            $newCookieValue .= $key . '=' . $value . '; ';
        }

        // 去掉最后的多余分号和空格
        return rtrim($newCookieValue, '; ');
    }
}
  • 将原始字符串中的unb和cookie2的值替换
$str = 'cna=Z10vHxyLLhkCAXPgqFaTMN9A; t=0dfd9e12691b5e686d8e406981bc179f; cookie2=113f243906b3776465e8fc246291d43d; xlly_s=1; _samesite_flag_=true; _tb_token_=548dd75bd1b39; unb=2209368547703; _hvn_lgc_=77; mtop_partitioned_detect=1; _m_h5_tk=518ab9b7ade30d1634c92f423962eb36_1729138819303; _m_h5_tk_enc=548aa63b41127caaeb4e9bc65e796a49; sdkSilent=1729216940928; sgcookie=E100MANykuWklerydA%2BMl9VIKBDu93fi6%2FAkc52GgwunEqZm9s%2F4QR3w70efJdK0OjoqaSSsURjd8rmp0UbOxRuxqtfyCuinoz28cswnbcjUUfk%3D; csg=96db0be1; havana_lgc2_77=eyJoaWQiOjIyMDkzNjg1NDc3MDMsInNnIjoiM2I1OTA0MDEzYTljZTcwZTRkZDkwYTQ1YzkzYjgxYzEiLCJzaXRlIjo3NywidG9rZW4iOiIxcEprcmNFY3FXa3l3U1RnY2hhT1U0dyJ9; havana_lgc_exp=1731722711974; isg=BHd3EOiN3F5lmFlq1jMGY7UyBm3BPEuetKiDGckl5cateJK60QzK7iOTWtgmkCMW; tfstk=gtErVp23SDVj2CSshxnEQC-n2_n-D0f1tkGIKJ2nFbcoAahntJFxdHw3VWPU_7-7OJf8TklmM2aWVWNeT7NjZ3wSNSl31SZI-6n7gSa0k_C-O8MUGr4Aw_EUpHk3KWB-OTQbe8nKx11_YGw8eWEySDXjrIXnLv1_7crXm8nKx19XxNsae50nOCBExtomdYJox2cl3jDsi3DHqvAc3vhmx30nrqAmevkk-vV3ntkKiXDL382H0AglCB0NDGfWA4cgEj-HbdHrrewWRh-a0Yuzx8cVL9rqU4lilG5xelygElHUvOYETzzuNxFFbso0gy2nuo1kfXaaCk3Uq9pS9zMtqYPhjFG0u-q-5-pPI-ija-DTu1--VRz0VqEGG3FUC7rE57scEWnoKW3TA1K-ZJ2TXPiNYFogg-qt-kCvvXabKko8sst492jrHBHmRXqLzBYnrxHq1tW4O4UiIC35k2YpJqmt3f6SFeLKrWMq1TgBJe3mtxl1Fw5..';
        dump($str);
        $newStr = ckStrReplace($str,[
            'unb' => '测试',
            'cookie2' => '测试2',
            'x5sec' => 'test2'
        ]);
        dump($newStr);
hanhanjun888@163.com

个人技术分享

php 操作cookie值
  • php 字符串cookie值数据拆分成数组,可以根据key的值进行替换,最后在组装成字符串
  • php 字符串cookie值数据拆分成数组,可以根据key的值进行替换,最后在组装成字符串
<?php
// 示例 Cookie 字符串
$cookieString = "user=hankin;age=30;city=hanzhou";

// 将字符串解析为数组
parse_str($cookieString, $cookieArray);

// 打印解析后的数组
print_r($cookieArray);

// 替换特定键的值
$cookieArray['city'] = 'shanghai';
$cookieArray['age'] = '35';

// 打印替换后的数组
print_r($cookieArray);

// 将数组重新组装为字符串
$newCookieString = http_build_query($cookieArray, '', ';');

// 打印重新组装后的字符串
echo $newCookieString;
?>
hanhanjun888@163.com

个人技术分享

fastadmin appendfieldlist 用法

添加页面

 <!--赞助商-->
    <div class="form-group row">
        <!--        <label class="control-label col-xs-12 col-sm-2">{:__('仪器产品')}:</label>-->
        <div class="col-xs-12">
            <table class="table fieldlist" data-template="eventtpl" data-name="row[yiqi_images]" id="second-table">
                <tr>
                    <td>{:__('赞助厂家')}</td>
                    <td>{:__('标题')}</td>
                    <td>{:__('图片')}<span style="color: red">670*176</span></td>
                    <td>{:__('链接')}</td>
                    <td>{:__('类型')}<span style="color: red">1内部;2外部</span></td>
                    <td width="100"></td>
                </tr>
                <tr>
                    <td colspan="3"><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></td>
                </tr>
            </table>

            <!--请注意实际开发中textarea应该添加个hidden进行隐藏-->
            <textarea name="row[yiqi_images]" class="form-control" style="display: none;"></textarea>
            <script id="eventtpl" type="text/html">
                <tr class="form-inline">
                    <td><input type="text" style="width: 200px;" name="<%=name%>[<%=index%>][id]" class="form-control selectpage" data-params='{"custom[status]":1}' data-source="manystore/shop" data-field="name" value="<%=row.id%>" placeholder="请选择赞助厂家"/></td>
                    <td><input type="text" name="<%=name%>[<%=index%>][title]" class="form-control" value="<%=row.title%>" placeholder="标题" size="10"/></td>
                    <td>
                        <input type="hidden" name="<%=name%>[<%=index%>][image]" id="c-image-<%=index%>" value="<%=row.image%>">
                        <!--@formatter:off-->
                        <button type="button" id="faupload-image" class="btn btn-danger faupload upload-image" data-input-id="c-image-<%=index%>" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false"></button>
                        <!--@formatter:on-->
                    </td>
                    <td><input type="text" name="<%=name%>[<%=index%>][url]" class="form-control" value="<%=row.url%>" placeholder="跳转链接" size="10"/></td>
                    <td><input type="text" name="<%=name%>[<%=index%>][type]" class="form-control" value="<%=row.type%>" placeholder="填1内部,2外部" size="10"/></td>
                    <td>
                        <!--下面的两个按钮务必保留-->
                        <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span>
                        <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
                    </td>
                </tr>
            </script>
        </div>
    </div>

编辑页面


<div class="form-group row"> <div class="col-xs-12"> <table class="table fieldlist" data-template="eventtpl" data-name="row[yiqi_images]" id="second-table"> <tr> <td>{:__('赞助厂家')}</td> <td>{:__('标题')}</td> <td>{:__('图片')}<span style="color: red">670*176</span></td> <td>{:__('链接')}</td> <td>{:__('类型')}<span style="color: red">1内部;2外部</span></td> <td width="100"></td> </tr> <tr> <td colspan="3"><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></td> </tr> </table> <!--请注意实际开发中textarea应该添加个hidden进行隐藏--> <textarea name="row[yiqi_images]" class="form-control" style="display: none;">{$row.yiqi_images|htmlentities}</textarea> <script id="eventtpl" type="text/html"> <tr class="form-inline"> <td><input type="text" style="width: 150px;" name="<%=name%>[<%=index%>][id]" class="form-control selectpage" data-params='{"custom[status]":1}' data-source="manystore/shop" data-field="name" value="<%=row.id%>" placeholder="请选择赞助厂家"/></td> <td><input type="text" style="width: 100px;" name="<%=name%>[<%=index%>][title]" class="form-control" value="<%=row.title%>"/></td> <td> <input type="hidden" style="width: 100px;" name="<%=name%>[<%=index%>][image]" id="c-image-<%=index%>" value="<%=row.image%>"> <button type="button" id="faupload-image" class="btn btn-danger faupload upload-image" data-input-id="c-image-<%=index%>" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false" <%if(row.image){%>style="background-image: url('<%=Fast.api.cdnurl(row.image)%>')"<%}%>></button> </td> <td><input type="text" name="<%=name%>[<%=index%>][url]" class="form-control" value="<%=row.url%>"/></td> <td><input type="text" style="width: 80px;" name="<%=name%>[<%=index%>][type]" class="form-control" value="<%=row.type%>"/></td> <td> <!--下面的两个按钮务必保留--> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span> </td> </tr> </script> </div> </div>

js代码

        add: function () {
            $(document).on("fa.event.appendfieldlist", "#second-table .btn-append", function (e, obj) {
                //绑定动态下拉组件
                Form.events.selectpage(obj);
                //绑定日期组件
                Form.events.datetimepicker(obj);
                //绑定上传组件
                Form.events.faupload(obj);

                //上传成功回调事件,变更按钮的背景
                $(".upload-image", obj).data("upload-success", function (data) {
                    $(this).css("background-image", "url('" + Fast.api.cdnurl(data.url) + "')");
                })
            });
            Controller.api.bindevent();
        },
        edit: function () {
            Template.helper("Fast", Fast);
            $(document).on("fa.event.appendfieldlist", "#second-table .btn-append", function (e, obj) {
                //绑定动态下拉组件
                Form.events.selectpage(obj);
                //绑定日期组件
                Form.events.datetimepicker(obj);
                //绑定上传组件
                Form.events.faupload(obj);

                //上传成功回调事件,变更按钮的背景
                $(".upload-image", obj).data("upload-success", function (data) {
                    $(this).css("background-image", "url('" + Fast.api.cdnurl(data.url) + "')");
                })
            });
            Controller.api.bindevent();
        },
hanhanjun888@163.com

个人技术分享

PHP使用无头浏览器如何帮助数据提取和抓取
php使用webdriver做采集的好处 自动化:WebDriver 可以模拟用户与浏览器的交互操作,如点击、输入文本、提交表单等。这使得您可以自动化执行各种网页操作,而无需手动进行。 多浏览器支持:WebDriver 支持多种浏览器,包括 Chrome、Firefox、Safari 等。这意味着您可以在不同的浏览器上运行和测试您的采集脚本,以确保在不同环境下的兼容性。 动态内容处理:许多网站使用 JavaScript 和 AJAX 技术来加载和更新内容。通过 WebDriver,您可以等待页面加载完成并获取完整的渲染后的页面内容,包括动态生成的内容。 数据抽取:WebDriver 提供了丰富的方法和选择器来定位和提取页面中的元素。您可以使用这些功能来获取所需数据,并将其保存到文件或数据库中进行进一步处理。 高度可定制化:WebDriver 允许您编写灵活且高度可定制化的采集脚本。您可以根据需要设置各种选项和参数,以适应不同网站和场景。 跨平台支持:WebDriver 是一个跨平台的工具,可以在 Windows、Mac 和 Linux 等操作系统上运行。这使得它成为一个广泛适用的采集解决方案。 使用方法 使用 WebDriver,您可以等待页面加载完成并获取完整的渲染后的页面内容,包括动态生成的内容。这意味着您可以采集到前后端分离网站上通过 JavaScript 或 AJAX 加载的数据。接下来让我自己动手写一个试试看。 安装浏览器chrome 1. 下载 Chrome 浏览器的安装包: wget https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm 2. 安装 Chrome 浏览器: sudo yum localinstall google-chrome-stable_current_x86_64.rpm 3. 验证 Chrome 是否成功安装: google-chrome --version 4. 下载对应版本的 ChromeDriver,并解压到指定目录(例如 /usr/local/bin): https://googlechromelabs.github.io/chrome-for-testing/ (各个版本的下载地址) wget https://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_linux64.zip unzip chromedriver_linux64.zip -d /usr/local/bin/ 5. 启动 ChromeDriver 服务: LANGUAGE=ZH-CN.UTF-8 /usr/local/bin/chromedriver --port=9515 6.成功运行后,您应该会看到类似以下输出: Starting ChromeDriver {version} on port 9515... Only local connections are allowed. Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe. ChromeDriver was started successfully. https://github.com/php-webdriver/php-webdriver PHP+WebDriver使用教程 https://github.com/php-webdriver/php-webdriver php代码执行
<?php
require_once('vendor/autoload.php');
use Facebook\WebDriver\Remote\DesiredCapabilities;

use Facebook\WebDriver\Remote\RemoteWebDriver;

use Facebook\WebDriver\Chrome\ChromeOptions;

$options = new ChromeOptions();

$options->addArguments(['--no-sandbox','--headless']);


$capabilities = DesiredCapabilities::chrome();

$capabilities->setCapability(ChromeOptions::CAPABILITY, $options);


$host = 'http://localhost:9555';

$driver = RemoteWebDriver::create($host, $capabilities);


// 访问百度网站

$driver->get('https://www.baidu.com');


// 获取页面源代码

$pageSource = $driver->getPageSource();


echo $pageSource;


// 关闭 WebDriver 会话

$driver->quit();
hanhanjun888@163.com

个人技术分享

微信公众号网页授权多域名解决方案(本地环境也可调用)
  • 实现微信授权域名中转实例
    • 微信授权回调域名(中转域名):www.test.com
    • 需要授权回调域名1:www.test1.com
    • 需要授权回调域名2:www.test2.com

一个公众号的域名授权数量是有限的,如果一个公众号需要绑定多个域名时怎么解决呢?这时候就需要用到域名中转

本地环境也可调用微信授权登录

  • 实现微信授权域名中转实例
    • 微信授权回调域名(中转域名):www.test.com
    • 需要授权回调域名1:www.test1.com
    • 需要授权回调域名2:www.test2.com

在中转域名网站 根目录下新建 wxLogin.php中编写发起授权代码

<?php
// +----------------------------------------------------------------------
// | 作者 hankin [ http://www.hankin.cn ]
// +----------------------------------------------------------------------
// | 版权所有 2024-06-27 13:06 hankin
// +----------------------------------------------------------------------
// | 官方网站: http://www.hankin.cn
// +----------------------------------------------------------------------
?>
<?php
$gzh_app_id = "公众号appid";//公众号appid
$gzh_app_secret = "公众号appsecret";//公众号appsecret
?>
<?php if(isset($_GET['redirectUrl']) && !empty($_GET['redirectUrl'])):?>
    <!--  获取跳转url地址  -->
    <script type="text/javascript">localStorage.setItem('redirectUrl','<?= $_GET['redirectUrl'];?>')</script>
<?php endif;?>

<?php if(isset($_GET['type']) && !empty($_GET['type'])):
    //发起授权
    $redirectUrl =  $_SERVER['REQUEST_SCHEME'] . '://'.  $_SERVER['SERVER_NAME'] . '/' . $_GET['type'] . '.php';
    //获取公众号授权拿到code
    $codeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$gzh_app_id."&redirect_uri=".urlencode($redirectUrl)."&response_type=code&scope=snsapi_userinfo&forcePopup=true&forceSnapShot=true&state=STATE#wechat_redirect";
    //header("location: ".$codeUrl);
    ?>
    <script type="text/javascript">
        //跳转code页面地址
        setTimeout(function(){
            window.location.href = '<?= $codeUrl;?>'
        },500)
    </script>
<?php endif;?>

<?php if(isset($_GET['code']) && !empty($_GET['code'])):
    //根据code获取微信用户信息
    $data = getSimpleUserInfo($_GET['code'], $gzh_app_id, $gzh_app_secret);
    ?>
    <?php
    //微信用户信息解析
    $ret['userinfo']['openid'] = $data['openid'] ?? '';//微信用户唯一标识 openid
    $ret['userinfo']['unionid'] = $data['unionid'] ?? '';//微信用户唯一标识 unionid
    $ret['userinfo']['nickname'] = $data['nickname']?? '';//微信用户昵称
    $ret['userinfo']['avatar'] = $data['headimgurl']?? '';//微信用户头像
    ?>
    <script type="text/javascript">
        //跳转回调地址
        window.location.href = localStorage.getItem('redirectUrl')+'?data=<?= urlencode(json_encode($ret));?>'
        //JSON.parse(decodeURIComponent(window.location.href.split('?data=')[1]))
    </script>
<?php endif;?>

<?php
function getSimpleUserInfo($code, $WECHAT_APPID, $WECHAT_APPSECRET)
{
    if (empty($code)) return array();
    //通过code换取网页授权access_token
    $access_token_url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $WECHAT_APPID . '&secret=' . $WECHAT_APPSECRET . '&code=' . $code . '&grant_type=authorization_code';
    $access_token_json = https_request($access_token_url);
    $access_token_array = json_decode($access_token_json, true);

    $openid = isset($access_token_array['openid']) ? $access_token_array['openid'] : '';
    $access_token = isset($access_token_array['access_token']) ? $access_token_array['access_token'] : '';

    $userinfo_url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $openid . '&lang=zh_CN';
    $userinfo_json = https_request($userinfo_url);

    $userinfo_array = json_decode($userinfo_json, true);

    return $userinfo_array;
}

//请求接口
function https_request($url)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $data = curl_exec($curl);
    if (curl_errno($curl)) {
        return 'ERROR ' . curl_error($curl);
    }
    curl_close($curl);
    return $data;
}



/**
 * 生成AJAX结果
 * @param $resultCode
 * @param null $message
 * @param null $data
 * @return array
 */
function generateAjaxResult($resultCode, $message = NULL, $data = NULL)
{
    exit(json_encode([
        'code' => $resultCode,
        'msg' => $message,
        'result' => $data,
    ]));
}



/**
 * AJAX成功返回数据
 * @param null $data
 * @return array
 */
function ajaxSuccess($data = NULL,$message = NULL)
{
    $result = generateAjaxResult(
        200,
        $message,
        $data
    );

    return $result;
}



/**
 * AJAX错误返回数据
 * @param null $message
 * @param int $resultCode
 * @param null $data
 * @return array
 */
function ajaxError($message = NULL, $resultCode = 1000, $data = NULL)
{
    $result = generateAjaxResult(
        $resultCode,
        $message,
        $data
    );

    return $result;
}
?>
  • 根据如上方式就可以实现微信授权域名中转
  • 访问 www.test1.com 站点时只需访问 https://www.test.com/wxLogin.php?type=wxLogin&redirectUrl=当前前端页面地址
  • 访问 www.test2.com 站点时只需访问 https://www.test.com/wxLogin.php?type=wxLogin&redirectUrl=当前前端页面地址