根据你提供的URL内容,
https://ip.tool.chinaz.com/112.37.131.232 这个页面确实包含了IP归属地信息(如“中国山东聊城”)。
由于你的PHPWind 8.7论坛使用GBK编码,而从站长之家获取的内容是UTF-8编码,关键在于处理好编码转换,并正确解析HTML。不过,直接解析完整网页HTML比较复杂且易失效,更推荐的方法是查找该网站是否提供更轻量的API接口。但从你给的页面看,没有直接显示简单的纯数据接口。
因此,这里提供一个基于正则匹配的PHP示例代码。它会获取网页内容,进行编码转换,然后提取归属地信息。这种方法比较直接,但请注意:如果站长之家修改页面结构,正则就需要相应调整。
php
<?php
/**
* 获取IP归属地(通过站长之家)
* @param string $ip 需要查询的IP地址
* @return string 返回归属地字符串,如“中国山东聊城”,失败返回空字符串
*/
function getIpLocationFromChinaz($ip) {
// 验证IP格式
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
return '';
}
// 构造查询URL
$url = 'https://ip.tool.chinaz.com/' . urlencode($ip);
// 初始化cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36');
$html = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// 请求失败
if ($httpCode != 200 || empty($html)) {
return '';
}
// 站长之家页面是UTF-8编码,论坛是GBK,先转为GBK以便内部处理或存入数据库
// 注意:如果接下来只是存储或显示,也可以保持UTF-8,但为了和论坛一致,这里转码
$html_gbk = mb_convert_encoding($html, 'GBK', 'UTF-8');
// 方法1:从HTML中匹配归属地(定位到“归属地:”后面的内容)
// 根据你提供的页面片段,归属地类似:<div>归属地:中国山东聊城</div>
// 正则:查找“归属地:”后面到下一个标签或文本结束的内容
$pattern = '/归属地[::]\s*([^<]+)/';
if (preg_match($pattern, $html_gbk, $matches)) {
$location = trim($matches[1]);
// 去除可能的空白字符和换行
$location = preg_replace('/\s+/', '', $location);
if (!empty($location)) {
return $location;
}
}
// 方法2:备选,查找类似 <span class="...">中国山东聊城</span> 的结构(如果方法1失效)
// 这个需要根据实际页面结构调整,这里给出通用思路
// 比如查找包含省份和城市的常见标签,但可靠性不如方法1
return '';
}
// 使用示例:
$onlinip = '112.37.131.232'; // 这是你论坛的当前在线IP变量
$location = getIpLocationFromChinaz($onlinip);
if ($location) {
echo "IP {$onlinip} 的归属地是:{$location}";
} else {
echo "未能获取到归属地信息。";
}
?>
重要注意事项:
编码处理:代码中先用mb_convert_encoding将UTF-8网页内容转为GBK,这样正则匹配出的中文就是GBK编码,能直接存入论坛数据库或与GBK页面一起显示。
正则表达式的脆弱性:站长之家的页面结构未来可能改变,导致/归属地[::]\s*([^<]+)/这个正则失效。如果失效,你需要查看网页源码,找到归属地附近更稳定的特征(比如某个唯一的id或class),然后调整正则。
性能与频率:每个在线IP都实时去抓取外部网站,会严重拖慢论坛速度,也容易被对方封IP。强烈建议增加缓存机制:
将查询过的IP和归属地存入论坛数据库(比如新建一张表ip_location_cache)。
每次查询前先检查缓存表,当天或几小时内有效则直接返回。
只有缓存中没有的IP才去请求站长之家。
法律与合规:请确认你的使用方式符合站长之家的服务条款。频繁的自动化请求可能违反其规定。
如果上述方法失效或不稳定,更可靠的替代方案:
推荐使用专业的IP数据服务API(很多提供免费额度),例如:
IPIP.net 或 纯真IP数据库(本地数据库,性能最好,无需网络请求)
淘宝IP地址库(
http://ip.taobao.com/,但稳定性一般)
ip-api.com(提供免费JSON接口,需注意频率)
例如使用 ip-api.com 的示例(返回JSON,编码处理更简单):
php
// 更稳定的方案:ip-api.com
$json = file_get_contents("http://ip-api.com/json/{$ip}?lang=zh-CN");
$data = json_decode($json, true);
if ($data['status'] == 'success') {
$location = $data['country'] . $data['regionName'] . $data['city'];
}
这个方法编码问题少,且速度快,推荐优先考虑。
总结:以上给出的PHPWind 8.7专用代码可以完成你的需求,但请注意健壮性和性能优化。如果项目重要,请优先采用本地IP数据库或稳定API。