【问题标题】:How do I extract the target URL from a Google search result?如何从 Google 搜索结果中提取目标 URL?
【发布时间】:2012-04-01 03:37:31
【问题描述】:

我正在尝试从 Google 搜索结果中提取 URL。我使用 Indy IdHTTP 从 Google 获取 HTML 结果,我使用Achmad Z's code for getting the link hrefs from the page。如何获取每个 URL 的真实链接目标,而不是通过 Google 重定向器的链接目标?


我试过了,但在这部分代码中出现“操作数不适用”错误:

function ToUTF8Encode(str: string): string;
var
  b: Byte;
begin
  for b in BytesOf(UTF8Encode(str)) do
  begin
    Result := Format('%s%s%.2x', [Result, '%', b]);
  end;
end;

我使用 Delphi 7 和 Indy 9.00.10。也许 indy 更新会有所帮助?

【问题讨论】:

  • 好的,告诉我们你尝试了什么以及这些尝试是如何失败的。
  • Google 会进行严重的浏览器嗅探点击计数,将您自制的用户代理屏蔽为 Opera 可能会有所帮助。

标签: delphi delphi-7


【解决方案1】:

如果我猜对了,您正在尝试使用 TIdHTTP.Get 方法获取 Google 搜索结果。如果是这样,那么
您绝对应该专注于一些 Google 搜索 API 实现,因为

  1. 以这种方式获取结果是不可能的,因为您无权访问搜索结果所在的 iframe 内的文档,因此在这种情况下使用 HTTP GET(或至少我还没有听说过可以做到这一点的请求)
  2. 这违反了 Google 政策,您应该改用适当的 Google 搜索 API,例如 Google SOAP Search API,还有多种类型的 Google 搜索 API 可用于各种目的

你可以找到例如here Delphi 包装器,带有用于 Google 搜索 API 的 demo 代码。我已经在 Windows 7/64 上使用 Delphi 2009 对其进行了测试,对我来说效果很好。

【讨论】:

  • 试过了,我得到'操作数在这部分代码中没有适用的错误:function ToUTF8Encode(str: string): string; var b:字节; begin for b in BytesOf(UTF8Encode(str)) do begin Result := Format('%s%s%.2x', [Result, '%', b]);结尾;我将 Delphi 7 与 Indy 9.00.10 一起使用。也许 indy 更新会有所帮助?
  • @Danijel,对不起,这是因为 for b in BytesOf 声明还没有在 Delphi 7 中。作为一个修补程序,您可以尝试用更新后的帖子替换原来的 ToUTF8Encode 函数。希望这将是最后一个不兼容的事情。无论如何,您仍然可以用一些编码 URL 地址的函数替换 ToUTF8Encode 函数。这是这个函数的唯一用途。
  • 感谢您帮助我尝试过,并使用 sh_web 和其他类型作为搜索类型,但我总是收到错误“模块中地址 xxxx 中的访问冲突”。谢谢你的帮助 。我不想再打扰你了,我似乎没有希望找到那个代码。不过会继续搜索。
  • 诉诸谷歌政策禁令对我来说似乎有问题,有正式声明吗?另外,iframe?
  • @Premature Optimization,您是否尝试过使用 TIdHTTP.Get 获取 Google 搜索网页?也许您对用户客户端的建议可能有效,但仍然是矫枉过正。
【解决方案2】:

在上一篇文章中,我尝试解释了为什么应该使用 Google Search API,在这篇文章中,我将尝试为您提供一个示例,希望它可以在您的 Delphi 7 中使用。

您需要拥有SuperObject(Delphi 的 JSON 解析器),我使用了 this version(此时是最新的)。然后你需要印地;如果可能的话,最好的办法是升级到最新版本。我使用的是 Delphi 2009 附带的那个,但我认为 TIdHTTP.Get 方法非常重要,它必须在您的 9.00.10 版本中也能正常工作。

现在您需要一个列表框和表单上的按钮、以下代码和一点运气(为了兼容性:)

您可以在前面提到的 DxGoogleSearchApi.pas 中看到 URL 请求构建,但最好遵循 Google Web Search API reference。在 DxGoogleSearchApi.pas 中,您可以获取灵感,例如如何获取多个页面。

所以以此为灵感

uses
  IdHTTP, IdURI, SuperObject;

const
  GSA_Version = '1.0';
  GSA_BaseURL = 'http://ajax.googleapis.com/ajax/services/search/';

procedure TForm1.GoogleSearch(const Text: string);
var
  I: Integer;
  RequestURL: string;
  HTTPObject: TIdHTTP;
  HTTPStream: TMemoryStream;
  JSONResult: ISuperObject;
  JSONResponse: ISuperObject;
begin
  RequestURL := TIdURI.URLEncode(GSA_BaseURL + 'web?v=' + GSA_Version + '&q=' + Text);

  HTTPObject := TIdHTTP.Create(nil);
  HTTPStream := TMemoryStream.Create;

  try
    HTTPObject.Get(RequestURL, HTTPStream);
    JSONResponse := TSuperObject.ParseStream(HTTPStream, True);

    if JSONResponse.I['responseStatus'] = 200 then
    begin
      ListBox1.Items.Add('Search time: ' + JSONResponse.S['responseData.cursor.searchResultTime']);
      ListBox1.Items.Add('Fetched count: ' + IntToStr(JSONResponse['responseData.results'].AsArray.Length));
      ListBox1.Items.Add('Total count: ' + JSONResponse.S['responseData.cursor.resultCount']);
      ListBox1.Items.Add('');

      for I := 0 to JSONResponse['responseData.results'].AsArray.Length - 1 do
      begin
        JSONResult := JSONResponse['responseData.results'].AsArray[I];
        ListBox1.Items.Add(JSONResult.S['unescapedUrl']);
      end;
    end;

  finally
    HTTPObject.Free;
    HTTPStream.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  GoogleSearch('Delphi');
end;

【讨论】:

  • 看来我注定要失败了,现在我得到 EidHttp 错误 Http 404 not found ,我的朋友会给我带来 Delphi 2009 ,这似乎是我唯一的选择,甚至 Marco Cantu 的 webfind 代码都不是t 为我工作 [marcocantu.com/code/md6htm/WebFind.htm] 并且它是为 Delphi 7 制作的,过程 TFindWebThread.HtmlToList 存在问题;我就是想不通:(
  • @Danijel,HTTP 404 表示您的 URL 请求错误。这很简单,只需将您传递给 TIdHTTP.Get 方法的 URL 地址粘贴到您的 Web 浏览器即可。你会得到同样的错误。如果您有正确的 URL,那么您将获得 JSON 结果,在您的浏览器中将是纯文本对象表示法。
  • @Danijel,尝试传递给 TIdHTTP.Get 例如http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=Delphi,你会得到正确的结果。
  • 我得到 404 并且错误指针设置为 JSONResponse := TSuperObject.ParseStream(HTTPStream, True);
  • 我想这样做但没有足够的代表能力,现在我已经接受了你的回答,再次感谢:)
【解决方案3】:

回答我的问题,也许它可以帮助某人: 正在获取网页:

memo1.Lines.Text := idhttp1.Get('http://ajax.googleapis.com/aja...tart=1&rsz=large&q=max');

提取网址:

function ExtractText(const Str, Delim1, Delim2: string; PosStart: integer; var PosEnd: integer): string;
var
  pos1, pos2: integer;
begin
  Result := '';
  pos1 := PosEx(Delim1, Str, PosStart);
  if pos1 > 0 then
  begin
    pos2 := PosEx(Delim2, Str, pos1 + Length(Delim1));
    if pos2 > 0 then
    begin
      PosEnd := pos2 + Length(Delim2);
      Result := Copy(Str, pos1 + Length(Delim1), pos2 - (pos1 + Length(Delim1)));
    end;
  end;
end;

然后在 Button1 上放:

procedure TForm1.Button1Click(Sender: TObject);
var Pos: integer;
    sText: string;
begin
  sText := ExtractText(Memo1.Lines.Text, '"url":"', '","visibleUrl"', 1, Pos);
  while sText <> '' do
  begin
    Memo2.Lines.Add(sText);
    sText := ExtractText(Memo1.Lines.Text, '"url":"', '","visibleUrl"', Pos, Pos);
  end;
end;

www.delphi.about.com 有很好的关于字符串操作的文档,Zarko Gajic 在那个网站上做得很好:) 注意:如果谷歌改变它的来源,这将是无用的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-15
    • 2013-01-30
    • 1970-01-01
    • 2020-03-19
    • 2020-06-27
    • 2023-02-05
    • 2018-02-05
    • 1970-01-01
    相关资源
    最近更新 更多