在開發網絡應用時,經常需要根據IP地址或域名獲取用戶所在城市信息,類似ip138網站提供的「您的IP:xxx.xxx.xxx.xxx 來自:北京市 聯通」功能。本文介紹如何使用Qt框架實現這一功能,並解決網頁重定向導致的數據抓取難題。
許多網上的示例代碼(如CSDN論壇帖子)已失效,原因是目標網站(iframe.ip138.com/ic.asp)更換了運行機制,可能引入了重定向,導致直接下載的頁面源碼不包含所需的IP和地址信息,雖然瀏覽器能正常顯示。
採用Qt的QNetworkAccessManager類發送GET請求,通過事件循環等待響應完成,再從返回的HTML中提取<center>標籤內的內容。
#define IP138 L"https://iframe.ip138.com/ic.asp"
QString getIpLocation() {
const QString URLSTR = QString::fromStdWString(IP138);
QUrl url(URLSTR);
QNetworkAccessManager manager;
QEventLoop loop;
// 發送GET請求
QNetworkReply *reply = manager.get(QNetworkRequest(url));
// 請求完成時退出事件循環
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec(); // 進入子事件循環等待
// 讀取並解析響應數據
QString code = reply->readAll();
QString lcenter = "<center>";
QString rcenter = "</center>";
int lIndex = code.indexOf(lcenter);
QString left = code.left(lIndex + lcenter.length());
code.replace(left, "");
int rIndex = code.indexOf(rcenter);
QString result = code.left(rIndex);
return result; // 返回「來自:北京市 聯通」等信息
}
QNetworkReply對象包含響應數據和頭部信息。finished()信號連接quit()槽實現阻塞等待。開發者也可自定義信號強制退出循環實現超時控制。<center></center>標籤間,通過字符串查找與截取提取核心數據。僅包含#include <QtNetwork>不夠,必須在項目.pro文件中添加網絡模塊:
QT += network
否則編譯會報找不到網絡類定義的錯誤。
QNetworkRequest不僅限於簡單GET請求,還可構建POST請求、設置請求頭、Cookie等,應用於:
響應頁面結構簡潔,核心信息集中在<center>標籤內,解析邏輯穩定可靠。
本方案通過Qt網絡模塊主動發起HTTP請求,繞過瀏覽器重定向機制直接獲取目標數據,代碼簡潔(約30行核心邏輯),穩定性高。開發者可根據實際業務需求擴展為通用的IP地理位置查詢組件,支持IPv4/IPv6、域名解析等高級功能。