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

Delphi调用Google Lens反向图搜获取手机型号失效问题求助

解决方案:Google Lens反向搜图提取手机型号(Delphi)

问题分析

你的代码依赖固定字符串片段匹配,但Google Lens的页面结构会随内容动态变化,不同图片对应的页面渲染逻辑可能不同,导致原有特征串失效。目标文本通常嵌入在页面的内联JSON数据块中,而非直接的HTML节点,所以普通HTML解析器无法直接定位。

可行方案:解析内联JSON数据

Google Lens的页面会将搜索结果数据放在AF_initDataCallback这样的内联JS变量里,我们可以提取这部分JSON内容并解析,从而稳定获取“相关搜索”的型号文本。

Delphi实现代码

uses
  System.Net.HttpClient, System.SysUtils, System.JSON, System.StrUtils;

function ExtractPhoneModelFromLens(const ImageURL: string): string;
var
  LHTTPClient: TNetHTTPClient;
  LResponseContent: string;
  LStartPos, LEndPos: Integer;
  LJSONStr: string;
  LJSONValue: TJSONValue;
  LJSONArray: TJSONArray;
  LItem: TJSONValue;
  LQueryObj: TJSONObject;
begin
  Result := '';
  LHTTPClient := TNetHTTPClient.Create(nil);
  try
    // 模拟浏览器请求头,避免被拦截
    LHTTPClient.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36';
    LHTTPClient.AcceptLanguage := 'en-US,en;q=0.5';
    LHTTPClient.Accept := 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
    
    // 请求Google Lens页面
    LResponseContent := LHTTPClient.Get('https://lens.google.com/uploadbyurl?url=' + ImageURL).ContentAsString;
    
    // 提取AF_initDataCallback中的JSON数据块
    LStartPos := Pos('AF_initDataCallback(', LResponseContent);
    if LStartPos = 0 then Exit;
    LStartPos := LStartPos + Length('AF_initDataCallback(');
    // 匹配对应的闭合括号(处理嵌套)
    LEndPos := LStartPos;
    var LBracketCount := 1;
    while LEndPos <= Length(LResponseContent) do
    begin
      case LResponseContent[LEndPos] of
        '(': Inc(LBracketCount);
        ')': Dec(LBracketCount);
      end;
      if LBracketCount = 0 then Break;
      Inc(LEndPos);
    end;
    if LEndPos >= Length(LResponseContent) then Exit;
    
    // 截取JSON字符串并清理(去掉末尾的分号)
    LJSONStr := Copy(LResponseContent, LStartPos, LEndPos - LStartPos);
    LJSONStr := Trim(LJSONStr);
    if EndsStr(';', LJSONStr) then
      LJSONStr := Copy(LJSONStr, 1, Length(LJSONStr)-1);
    
    // 解析JSON
    LJSONValue := TJSONObject.ParseJSONValue(LJSONStr);
    if not Assigned(LJSONValue) then Exit;
    try
      // 遍历JSON结构,找到相关搜索的query字段(路径可能需根据实际调整)
      if LJSONValue is TJSONArray then
      begin
        LJSONArray := TJSONArray(LJSONValue);
        // 这里的索引需要根据实际JSON结构调整,示例为常见路径
        if LJSONArray.Count > 1 then
        begin
          var LInnerArray := LJSONArray.Items[1] as TJSONArray;
          if Assigned(LInnerArray) and (LInnerArray.Count > 0) then
          begin
            var LDataBlock := LInnerArray.Items[0] as TJSONArray;
            if Assigned(LDataBlock) and (LDataBlock.Count > 5) then
            begin
              var LRelatedSearches := LDataBlock.Items[5] as TJSONArray;
              if Assigned(LRelatedSearches) and (LRelatedSearches.Count > 0) then
              begin
                // 取第一个相关搜索的query
                LItem := LRelatedSearches.Items[0];
                if LItem is TJSONArray then
                begin
                  LQueryObj := TJSONArray(LItem).Items[0] as TJSONObject;
                  if Assigned(LQueryObj) then
                    Result := LQueryObj.GetValue<string>('query');
                end;
              end;
            end;
          end;
        end;
      end;
    finally
      LJSONValue.Free;
    end;
  finally
    LHTTPClient.Free;
  end;
end;

// 使用示例
procedure TForm1.Button1Click(Sender: TObject);
var
  Model: string;
begin
  // 测试第二个图片
  Model := ExtractPhoneModelFromLens('https://fdn2.gsmarena.com/vv/bigpic/samsung-galaxy-m32-5g-new.jpg');
  if Model <> '' then
    ShowMessage('提取到型号:' + Model)
  else
    ShowMessage('未找到型号');
end;

注意事项

  • Google的内联JSON结构可能会随时调整,若后续失效,需重新查看页面源码,调整JSON解析的路径索引。
  • 若请求被Google拦截,可尝试添加更多请求头(如Referer),或使用代理IP。
  • 不要频繁请求,避免触发Google的反爬机制。

内容的提问来源于stack exchange,提问作者Ismail Dz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 19:18:26