いつもお世話になります。
Delphi Commminity EdでMacOS用のMemo帳を作っているのですが、
以下の点で困っております。
選択文字列をGoogleで検索するために以下のコードを記述しています。
Moji:='あいうえお';
SURL:='https://www.google.com/search?hl=ja&output=search&q='+Moji;
_system(PAnsiChar('open ' + AnsiString(SURL)));//MacOSの場合
ところが、ブラウザ(Chrome)でGoogleは開くのですが、
URL部分は、
https://www.google.com/search?hl=ja&output=search&q=あいうえお
にはなっておらず、下記のようになってしまいます。
https://www.google.com/webhp?hl=ja
Memo1.Text:=SURL と追加してみると、
SURL部分にはきちんと下記の値が代入されています。
https://www.google.com/search?hl=ja&output=search&q=あいうえお
何が原因なのでしょうか?
MacOS のことは分かりませんが,
Google 日本のウェブサイトは https://www.google.com/
https://www.google.com/webhp?hl=ja
は日本語表示されている Google のウェブページのことです.
つまり,単に Google の大元のウェブページを表示しているだけだと思います.
と言うことで,
>何が原因なのでしょうか?
検索オプションの指定の問題なのではないかと思います.
あるサイト内の URL を指定した時,該当ページがない時の動作のようなものだと思います.
# MacOS って AnsiString 使うんですね.
単純に、アンパサントのエスケープ漏れの気がします...
編集 削除Mr.Xrayさん、Novさん
お世話になります。書き込みありがとうございます。
実は、Windows版では下記で正常に動作しています。
var
SURL:String;
GoogleS:String;
begin
GoogleS:='https://www.google.com/search?hl=ja&output=search&q=';
SURL:=GoogleS + HTTPEncode(UTF8Encode(Edit1.Text));
ShellExecute(Application.Handle,'open',Pchar(SURL),NiL,NiL,SW_SHOW);
end;
Mac用のGoogleChromだと仕様が異なるのでしょうか、
不思議なのですが、
https://www.google.com/search?hl=ja&output=search&q=あいうえお 部分を
Google Chrom Mac版のURLフィールドに直接コピペして改行すると
検索後のページが正常に表示されています。
Mac版だとShellExecuteではなく、_system() 関数を使っていて
「『open URL文字列』 というコマンドライン文字列を作って、それをシェルに実行させる」という手順になっていますよね?
そのような場合、'&' とか '|' とか '<' とか '>' とかいった文字はシェルにとって特別な意味を持つので、
そういう特殊な解釈をされたくなければエスケープする必要があります。
(ShellExecuteの場合は、cmd.exeを経由するわけではないのでそのような配慮が不要だっただけです)
Macのコマンドラインの仕様はよく知りませんが、一般的には引数を二重引用符("")で囲むとかですかね?
_system('open "' + URL文字列 + '"');
ついでですが、渡される文字列に&とか引用符のような特殊文字が含まれているとやはり困ったことになるので、URLエンコードしておいた方が良いかと。
SURL := ... TIdURI.URLEncode(検索する文字列);
質問者ではないですが…、
なるほど、URLのうち & の前までの
https://www.google.com/search?hl=ja をブラウザへ入れて移動すると、
https://www.google.com/webhp?hl=ja に遷移しますね。
ところで、
> _system(PAnsiChar('open ' + AnsiString(SURL)));//MacOSの場合
これだと検索クエリがAnsiString、つまりシフトJISに限定されてしまいますよね?
「OSX ブラウザ Delphi」で検索してみたら別の方法がありました。
FireMonkey - OS X で URLをデフォルトブラウザで開く - MASA Lab softlab
http://softlab.masa-lab.net/modules/d3blog/details.php?bid=21
こちらだとUnicodeで行けるような気が? 試してみてはいかがでしょう。
URLエンコード(パーセントエンコード)には、これはどうでしょう。HTTPEncodeは非推奨のようなので。
http://docwiki.embarcadero.com/Libraries/ja/System.NetEncoding.TURLEncoding
以上、環境がないためまったく試していませんから無責任ですが、ご参考までに。
torさん Harryさん
書き込みありがとうございます。
KStr:='あいうえお';
SURL:=TIdURI.URLEncode('https://www.google.com/search?hl=ja&output=search&q='+KStr);//+Memo1.SelText;
_system(PAnsiChar('open ' + AnsiString(SURL)));//MacOSの場合
Memo1.Text:= SURL;
上記のコードでもやはり https://www.google.com/webhp?hl=ja のままとなります。
正常にエンコードされているのは、 Memo1.Text:= SURL; 部分で確認しています。
ためしに、GoogleChromのMac版で、検索文字列のあいうえおを検索したときに生成されるURL【下記①】を直接上記のSURLに
セットしてみましたが、やはり症状は変わらないようです。EnCodeの問題ではないのでしょうか?
ただ気になるのが、Windows用には出てこないUTF8以外の文字列です。
もう一つ不思議なのが、
https://www.google.com/search?hl=ja&output=search&q=あいうえお 部分を
Google Chrom Mac版のURLフィールドに直接コピペして改行するとURLはコンバートされずにそのままそのURLが表示され
検索結果画面が正常に表示されているという点です。
検索文字列を付加してでMemo帳からGoogle起動する時に、検索文字列部分が
無視されてhttps://www.google.com/webhp?hl=ja へ全てリダイレクトされているという感じです。
Chrome Mac版の仕様なのでしょうか??
【下記①】は、https://www.google.com/ で表示させたあとに、Google検索フィールドから あいうえお と検索した際に
URL部分に表記されているURLです。
SURL:='https://www.google.com/search?hl=ja&source=hp&ei=8UJhW-H4MZLXhwP-5JyYCA&q=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A'
+'&oq=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A&gs_l=psy-ab.3..35i39k1j0i131i4k1j0i4k1j0i131i4k1j0i4k1l4.40489.43943.0.44487.13.8.'
+'2.0.0.0.91.554.7.8.0....0...1c.1j4.64.psy-ab..3.10.753.6..0j0i131k1j0i67k1.194.G-yNQr6sOzE ';
検索文字列を
KStr:='あいうえお';
ではなく,例えば
KStr:='Delphi';
にするとどうなりますか ?
で、'open "' + URL文字列 + '"' と二重引用符で囲む方は試してみたのでしょうか?
今回の問題の本質は、例えば
> _system('open a&b&c')
とsystem関数を使って実行すると、その中の "&" がシェルによって
「複数のコマンドを並列して実行しろ」という指示だと解釈されるということにあります。
上の文字列は、次のように3つのコマンドを実行する指示になります。
1. 「open a」というコマンドをバックグラウンドで実行して、
2. 「b」というコマンドをバックグラウンドで実行して
3. 「c」というコマンドを実行する
このように解釈されるのは、URLエンコードしても防ぐことはできません
(URLエンコードしても '&' は '&' のままなので)。
防ぐためには、"" で囲んで「この中は特別な解釈をしないで、一塊の文字列として扱ってください」ということをシェルに伝える必要があります。
> _system('open "a&b&c"')
としなくてはいけないのです。あるいは & の前に \ を付けてエスケープして
> _system('oepn a\&b\&c')
とします。これで、
1. 「open」コマンドに「a&b&c」という文字列を引数として与えて実行する
という本来意図した意味になります、たぶん。
Mr.xrayさん、torさん
お世話になります。
教えていただきました下記①では出来ました。本当にありがとうございます。
試してみてはいたのですが、セットの仕方が間違っていたようで・・・
ただ、URLを変数SURLにセットして実行するとエラーなくコンパイルは出来ますが、
Paseverのターミナル上では、>sh: o: command not found と出てブラウザも起動しない状況です。
①_system(PAnsiChar('open "https://www.google.com/search?hl=ja&output=search&q=Delphi"'));//MacOSの場合
②_system(PAnsiChar('open "' + SURL +'"'));//MacOSの場合
念のため、きちんとセットされているかも下記で試してみましたが、
Memo1.text:='open "' + SURL +'"'
open "https://www.google.com/search?hl=ja&output=search&q=Delphi" と表記されていますので変数セットは大丈夫だと思うのですが・・・
このやり方はどうでしょう?
検索文字列の日本語部分はパーセントエンコーディングを行う必要があります。
パーセントエンコーディング
https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%82%BB%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0
下記のコードは、エディットに検索文字列を入れ、検索ボタンを押すとブラウザが開くという単純なコードです。
検索文字列「あいうえお」でもOK。
Macintosh実機で実行させてみましたが、普通に動きました。
手元の環境のMacintoshには、Google Chromeを入れていないので、Safariで起動しますが。
unit MainUnit;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls, FMX.Controls.Presentation, FMX.Edit,
IdURI,
Macapi.Helpers, Macapi.Foundation, Macapi.AppKit;
type
TMainForm = class( TForm )
SearchEdit : TEdit;
SearchButton : TButton;
procedure SearchButtonClick( Sender : TObject );
procedure OpenBrowser( const AURL : String; const ASearchText : String );
private
{ private 宣言 }
public
{ public 宣言 }
end;
var
MainForm : TMainForm;
implementation
{$R *.fmx}
// 検索ボタン押下時処理
procedure TMainForm.SearchButtonClick( Sender : TObject );
begin
OpenBrowser( 'https://www.google.com/search?hl=ja&output=search&q=', SearchEdit.Text );
end;
// ブラウザオープン処理
procedure TMainForm.OpenBrowser( const AURL : String; const ASearchText : String );
var
WorkSpace : NSWorkspace;
URL : NSURL;
begin
WorkSpace := TNSWorkspace.Wrap( TNSWorkspace.OCClass.sharedWorkspace );
URL := TNSURL .Wrap( TNSURL.OCClass.URLWithString( StrToNSStr( TIdURI.URLEncode( AURL + ASearchText ) ) ) );
WorkSpace.openURL( URL );
end;
end.
【環境】
・Windows 10 - Delphi 10.2.3 Tokyo
・macOS 10.13.4
KONNNOYAさん
いつもありがとうございます。
ご提供いただきましたコードでSafari、Chrom(それぞれデフォルトブラウザを変更して)両方で
&を含まない文字列でしたら検索はできるのですが、
例えば、
DELPHI Q&A で検索をすると
DELPHI Q で検索をしてしまいます。
&を含む検索文字列の場合このようになるようなので、試しに DELPHI Q\&A としみても変わりはありませんでした。
たびたびで申し訳ございませんが、他に対応方法はございますでしょうか?
あらら、その様な事が(汗
試してみた所、ホントですね。
こちらではどうでしょうか?
System.NetEncoding の TNetEncoding.URL.Encodeならうまくいくようです。
※ さっきのサンプルで、URLを含めてのエンコードも良くなかったです。
検索ワードのみをエンコードする様にしました。
uses
…System.NetEncoding;
URL := TNSURL.Wrap( TNSURL.OCClass.URLWithString( StrToNSStr( AURL + TNetEncoding.URL.Encode( SearchWord ) ) ) );
うまくいくのですが、ただ気になる記事を発見しました。
https://qiita.com/pik/items/2e6355c3f674699a1340
Noby様の健闘を祈ります。
KONNOYAさん
お蔭様で、出来ました!本当にありがとうございました。
Mr.XRAYさん、Novさん、torさん、Harry さん
皆様、本当にご親切に教えていただきまして本当にありがとうございます。
いつも助けてくださって心から感謝申し上げます。
しかし、マルチデバイス(今回はiOSのみ向けですが)用の開発は
VCLとは結構異なるようで、結構苦労しそうです(^^;)