質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Apache Solr

Solrは、全文検索ライブラリである Luceneを用いたオープンソースの検索エンジンサーバです。Javaで記述されており、高い全文検索能力を持ちます。ドキュメントの登録には、XML/JSON/CSVなどを用い、ファセット検索機能も備わっています。

Q&A

解決済

1回答

768閲覧

httpのリクエストについて

todasan

総合スコア78

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Apache Solr

Solrは、全文検索ライブラリである Luceneを用いたオープンソースの検索エンジンサーバです。Javaで記述されており、高い全文検索能力を持ちます。ドキュメントの登録には、XML/JSON/CSVなどを用い、ファセット検索機能も備わっています。

0グッド

0クリップ

投稿2023/01/10 06:33

編集2023/01/12 10:15

solrという検索エンジンに、httpのリクエストをしています。
以下は一般的なhttpリクエストの質問です。

q4 = 'val:"mul(pow(0.5,div(geodist(), 1)),37140)"'
q = 'q=' + urllib.parse.quote(q4)

q4の複雑な文字列に対して、httpリクエストを行う場合に、
urllib.parse.quoteにより、日本語でも可能になると、
分かりました。
上記のq4を変換すると、リクエストとして、下記のように、
文字コードに変換されます。
val%3A%22mul%28pow%280.5%2Cdiv%28geodist%28%29%2C%201%29%29%2C37140%29%22
しかし、solrという検索エンジンに、リクエストを送ると、
エラーになります。
一般的に上記の方法で何か間違った方法があり、何かおかしい点は、
ありますか。

・POSTMANのパラメータ { "rsc":"z_poi", "keyword":"ディズニーランド", "sortType":1, "longitude":140, "latitude":135, "rangetype":1, "polygon":[ { "latitude": 140, "longitude": 138 }, { "latitude": 145, "longitude": 145 }, { "latitude": 139, "longitude": 145 }, { "latitude": 138, "longitude": 139 }, { "latitude": 140, "longitude": 138 } ], "pos":1, "num":20 } ・solrquery.py import urllib.parse from janus.azazel.azazel import Azazel class SolrQuery: def __init__(self) -> None: self._logger = Azazel() def createPoiSearchQuary(self, req_data): print('req_data') print(req_data) self._logger.writeLogDebug("SolrQuery::createPoiSearchQuery start") # フリーワード【keyword】、ジャンル【genre】に以下の特殊文字が入ってる場合、その前に『/』マークを付ける。 if not req_data.get('keyword') is None: print('test1') req_data['keyword'] = SolrQuery.escapeword(req_data.get('keyword')) if not req_data.get('genre') is None: print('test2') req_data['genre'] = SolrQuery.escapeword(req_data.get('genre')) keywordlist = 1 # keywordlist = req_data.get('keyword').split(' ') if keywordlist > 1: #q1の式作成 q1 = '' count = 0 for kword in keywordlist: #重みづけ処理 kword = SolrQuery.waitplus(kword) if count > 0: q1 += 'AND ' + kword else: q1 += kword count += 1 q1 = '(' + q1 + ')' else: kword = req_data.get('keyword') kword = SolrQuery.waitplus(kword) q1 = kword self._logger.writeLogDebug('q1: {}'.format(q1)) #q2の式作成 q2 = '' if not req_data.get('genre') is None: genrelist = req_data.get('genre').split(',') count = 0 for gword in genrelist: if count > 0: q2 += ' OR (fq_genre_key_array:' + gword + ')' else: q2 += '(fq_genre_key_array:' + gword + ')' count += 1 q2 = ' AND (' + q2 + ')^=1' q2 = str(q2).replace("[","").replace("]","").replace("/","") q2 = '' print('q2') print(q2) #q3の式作成 q3 = '' if not req_data.get('area') is None: arealist = req_data.get('area').split(' ') for area in arealist: if len(req_data.get('area')) == 2: q3 += '(prefcode:' + area + ')' else: q3 += 'OR (prefcode:' + area[0:1] + ' AND ' + area[2:4] + ')' q3 = ' AND (' + q3 + ')^=1' # q = '(' + q1 + q2 + q3 + ')' q = q1 + q2 + q3 print('q') print(q) #置換前 置換後 後で作成 #q4の式作成 q4 = '' req_sort = req_data.get('sort') req_rangetype = req_data.get('rangetype') print('test10') print(req_sort,req_rangetype) #検索パラメータ設定 if req_data.get('radius') is None: req_data['radius'] = 10000 if req_sort == 1 or req_sort == 2: if req_sort == 1 and req_rangetype == 1: print('test5') # q4 = '_val_:"mul(pow(0.5,div(geodist(),' + str(req_data.get('radius')) + ' / 1000 / 2)),37140)"' q4 = '_val_:mul(pow(0.5,div(geodist(), 1)),37140)' elif req_sort == 1 and req_rangetype == 2: # q4 = '_val_:"mul(pow(0.5,div(geodist(),' + str(req_data.get('radius')) + ' / 1000 / 2)),37140)"' q4 = '_val_:mul(pow(0.5,div(geodist(), 1)),37140)' elif req_sort == 2 and req_rangetype == 1: # q4 = '_val_:"mul(pow(0.5,div(geodist(),' + str(req_data.get('radius')) + ' / 1000 / 2)),37140)"' q4 = '_val_:mul(pow(0.5,div(geodist(), 1)),37140)' elif req_sort == 2 and req_rangetype == 2: # q4 = '_val_:"mul(pow(0.5,div(geodist(),' + str(req_data.get('radius')) + ' / 1000 / 2)),37140)"' q4 = '_val_:mul(pow(0.5,div(geodist(), 1)),37140)' print('q4') print(q4) amp = '&' d = '&d=' + urllib.parse.quote(str(req_data.get('radius') // 1000)) # d = 'd=' + urllib.parse.quote(str(req_data.get('radius') // 1000)) print('d') print(d) fl = amp + 'fl=' + urllib.parse.quote('*,score,distance:geodist()') if not req_data.get('lonlat') is None else '' print('fl') print(req_data.get('lonlat')) print(fl) fq = amp + 'fq=' + urllib.parse.quote('{!geofilt}') if not req_data.get('lonlat') is None else '' print('fq') print(fq) # indent = 'indent=' + urllib.parse.quote('true') indent = amp +'indent=' + urllib.parse.quote('true') print('indent') print(indent) pt = amp + 'pt=' + urllib.parse.quote(str(SolrQuery.ptset(req_data.get('lonlat')))) if not req_data.get('lonlat') is None else '' print('pt') print(pt) qop = amp + 'q.op=' + urllib.parse.quote('OR') print('qop') print(qop) # q = amp + 'q=' + urllib.parse.quote(q + ' ' + q4) q = 'q=' + urllib.parse.quote(q + ' ' + q4) print('q') print(q) sfield = amp + 'sfield=' + urllib.parse.quote('geo_p_wgs') print('sfield') print(sfield) sort = amp + 'sort=' + urllib.parse.quote('score desc,uniquekey asc') if not req_data.get('lonlat') is None else '' print('sort') print(sort) if req_sort == 3: sort = amp + 'sort=' + urllib.parse.quote('yomi desc,uniquekey asc') if not req_data.get('lonlat') is None else '' fl = amp + 'fl=' + urllib.parse.quote('*,score') if not req_data.get('lonlat') is None else '' deftype = amp + 'deftype=' + urllib.parse.quote('edimax') print('deftype') print(deftype) start = amp + 'start=' + urllib.parse.quote(str(req_data.get('pos'))) if not req_data.get('pos') is None else '' print('start') print(start) rows = amp + 'rows=' + urllib.parse.quote(str(req_data.get('num'))) if not req_data.get('num') is None else '' print('rows') print(rows) # query = indent + qop + q + sfield + sort + deftype + start + rows + d # query = indent + qop + q + sfield + sort + deftype + start + rows + d + fl + fq + pt # query = q + qop + indent + fl + sort + sfield + pt + fq + deftype + start + rows + d query = q + qop + indent + fl + sort + sfield + pt + fq print('query') print(query) ・呼び出し元 solrquery = SolrQuery() query = solrquery.createPoiSearchQuary(req_data)↑上記の関数 res = SolrAccess.execute(query, CORE10)↓下記のexecute def execute(query:str, core:str, data:dict= {}): # 送信先のURL(開発環境疎通確認用) #url = 'http://solr-dev.dev-financial-nsw.com/solr/zennrin/select?indent=true&q.op=OR&q=*%3A*' # 送信先のURL(開発環境用) url = URL.format(core) + query # Basic認証の情報(開発環境用) user = USER password = PASS # Basic認証用の文字列を作成. basic_user_and_pasword = base64.b64encode('{}:{}'.format(user, password).encode('utf-8')) # Basic認証付きの、POSTリクエストを作成する. request = urllib.request.Request(url, headers={ "Authorization": "Basic " + basic_user_and_pasword.decode('utf-8') , "Content-Type" : "application/json", }, method='POST', data=json.dumps(data).encode('utf-8')) # 送信して、レスポンスを受け取る. con = urllib.request.urlopen(request) res = simplejson.load(con) return res
・エラーの内容 nus\solrAccess\solraccess.py", line 71, in execute con = urllib.request.urlopen(request) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\urllib\request.py", line 216, in urlopen return opener.open(url, data, timeout) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\urllib\request.py", line 525, in open response = meth(req, response) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\urllib\request.py", line 634, in http_response response = self.parent.error( File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\urllib\request.py", line 563, in error return self._call_chain(*args) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\urllib\request.py", line 496, in _call_chain result = func(*args) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2544.0_x64__qbz5n2kfra8p0\lib\urllib\request.py", line 643, in http_error_default raise HTTPError(req.full_url, code, msg, hdrs, fp) urllib.error.HTTPError: HTTP Error 400: Bad Request

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2023/01/10 06:45

実際のコードとエラー詳細を提示ください。
int32_t

2023/01/10 06:58

solr とは何か、URLなど詳細を書いてください。 ブラウザで検索した場合のURLと、コードで作ったURLではどういう差がありますか?
todasan

2023/01/10 07:08

can110さん 実際のコードとエラー詳細を記載しました。
todasan

2023/01/10 07:14

int32_t さん apache solrと呼ばれる検索エンジンです。 ブラウザで検索した場合は、成功しました。 その内容を載せました。
can110

2023/01/10 07:23

- query変数にクエリ文字列らしきものを格納しているようだがprintしているだけに見える。 - 実際にHTTPリクエストしているコードが見当たらない。 などなど基本的な動きがよく分からないので、もう少し具体的に - 全体的な動作の流れや入出力データの説明、実際に通信している部分のコード - 正常な場合と(日本語を含む?)異常な場合の送信データ内容 などを提示しないと適切な回答得るのは難しいと思います。
todasan

2023/01/10 08:04 編集

can110さん 了解しました。HTTPリクエストをしているコードを、記載しました。
can110

2023/01/10 09:00

質問本文には記載ありませんが、JSON Request APIを使っているということでしょうか?
todasan

2023/01/10 10:38

can110 さん urlにquery変数が入ります。 pythonのurllib.requestを以下のように、使っています。 ----------------------------------------- import urllib.request request = urllib.request.Request(url, headers={ "Authorization": "Basic " + basic_user_and_pasword.decode('utf-8') , "Content-Type" : "application/json", }, method='POST', data=json.dumps(data).encode('utf-8')) -----------------------------------------
todasan

2023/01/11 00:03

can110 さん クエリのリクエストの部分が以下になります。 --------------------------------------------------- q=%28name%3A%E3%83%87%E3%82%A3%E3%82%BA%E3%83%8B%E3%83%BC%E3%83%A9%E3%83%B3%E3%83%89%5E40.0%20OR%20genre_name_array%3A%E3%83%87%E3%82%A3%E3%82%BA%E3%83%8B%E3%83%BC%E3%83%A9%E3%83%B3%E3%83%89%5E80.0%%20_val_%3Amul%28pow%280.5%2Cdiv%28geodist%28%29%2C%201%29%29%2C37140%29&q.op=OR&indent=true&fl=%2A%2Cscore%2Cdistance%3Ageodist%28%29&sort=score%20desc%2Cuniquekey%20asc&sfield=geo_p_wgs&pt=135%2C140&fq=%7B%21geofilt%7D --------------------------------------------------- sfield=geo_p_wgsなどとしています。上記のリンクの説明にも、上記のような書き方があります。 下記のurlをブラウザに、直入力すると、成功します。 --------------------------------------------------- http://solr-dev.dev-financial-nsw.com/solr/zennrin/select?q=name:ディズニーランド^40.0 OR genre_name_array:ディズニーランド^300.0 OR yomi:ディズニーランド^60.0 OR name_morph_sym:ディズニーランド^20.0 OR name_bigram:ディズニーランド^10.0 OR yomi_morph:ディズニーランド^10.0 OR yomi_bigram:ディズニーランド^10.0 _val_:"mul(pow(0.5,div(geodist(), 1)),37140)"&q.op=OR&indent=true&fl=*,score,distance:geodist()&sort=score desc,uniquekey asc&sfield=geo_p_wgs&pt=35.73016903373604,139.74800272437313&d=2&fq={!geofilt} --------------------------------------------------- q=name以降は文字化けはしていますが、上記と同じように、記載しても、エラーになります。
todasan

2023/01/11 01:13

can110 さん 自己解決しました。ありがとうございます。
can110

2023/01/11 05:30

どのような方法で解決したのでしょうか?
todasan

2023/01/11 05:49

can110 さん 上記の直入力のurlをqに入力しました。ptが35,140に直しました。dを100に直しました。 _val_:"mul(pow(0.5,div(geodist()1)),37140)"が迷っていた点で、"をつけてクオリを実装したら 動きました。成功したurlをqにそのまま反映させました。
can110

2023/01/11 06:21

解決した方法を回答に書くべきだと思いますが。
todasan

2023/01/11 06:31

can110 さん 了解しました。回答は回答に上記のような内容で書いた方がいいですか。 もっと詳しく書いた方がいいですか。 明日中には書きます。
can110

2023/01/11 07:06

- どこをどのように修正したのか(修正前と後を具体的、明確に記す) - なぜそのように修正したのか(原因は何だったのかを記す) といったことが分かるように書くとよいと思います。
guest

回答1

0

自己解決

上記のソースの
q4 = 'val:mul(pow(0.5,div(geodist(), 1)),37140)'を
q4 = 'val:"mul(pow(0.5,div(geodist(), 1)),37140)"'に変更しました。
そうなると、直入力で取り出しに、成功したクエリ文字列と、同じになります。
POSTMANの値を"longitude":140,"latitude":35に、変更しました。
変更前の値の、"longitude":140,"latitude":135は、取り扱う経度の範囲外でした。
クエリのptの部分です。

投稿2023/01/11 01:14

編集2023/01/12 01:15
todasan

総合スコア78

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問