syun_nissi
@syun_nissi (syun nissi)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

urllib.error.HTTPError: HTTP Error 400: Bad Request について

Q&A

Closed

解決したいこと

python参考書に記載のコードを実行するとタイトルの通りHTTPエラーが出てしまいます。
コードが長くて恐縮ですが、記載します。
わかりづらいかと思いますが、何かヒントになるようなアドバイスなどがあればいただけますと幸いです。

発生している問題・エラー

urllib.error.HTTPError: HTTP Error 400: Bad Request

該当するソースコード

import json

import sqlitedatastore as datastore
import solrindexer as indexer
from annoutil import find_x_including_y

#アノテーションのデータを文単位でsolrに登録する
def load_sentence():
    data=[]
    for doc_id in datastore.get_all_ids(limit=-1):
        row=datastore.get(doc_id,["content","meta_info"])
        text=row["content"]
        meta_info=json.loads(row["meta_info"])
        for i,sent in enumerate(datastore.get_annotation(doc_id,"sentence")):
            #solrへ登録するデータ構造へ変換
            data.append({
                "id":               "{0:d}.{1:s}.{2:d}".format(doc_id,"sentence",i),
                "doc_id_i":         "doc_id",
                "anno_id_i":        i,         
                "name_s":           "sentence",   
                "sentence_txt_ja":  text[sent["begin"]:sent["end"]],
                "title_txt_ja":     meta_info["title"],
                "url_s":            meta_info["url"],
            })

    #solrへ登録を実行
    indexer.load("anno",data)

#affiliationアノテーションで検索できるようにsolrに登録
def load_affiliation():
    anno_name="affiliation"
    data=[]
    for doc_id in datastore.get_all_ids(limit=-1):
        row=datastore.get(doc_id,["content","meta_info"])
        text=row["content"]
        meta_info=json.loads(row["meta_info"])
        sents=datastore.get_annotation(doc_id,"sentence")
        for i, anno in enumerate(datastore.get_annotation(doc_id,anno_name)):
            #solrへ登録するデータ構造へ変換
            #sentsの中からannoを含むデータを返す。sentenceの中からaffiliationアノテーションを探す。
            sent=find_x_including_y(sents,anno)
            data.append({
                "id":               "{0:d}.{1:s}.{2:d}".format(doc_id,"anno_name",i),
                "doc_id_i":         "doc_id",
                "anno_id_i":        i,
                "name_s":           "sentence",
                "sentence_txt_ja":  text[sent["begin"]:sent["end"]],
                "anno_name + '_txt_ja'":text[anno["begin"]:anno["end"]],   #新しく追加したフィールド。affiliationのアノテーションがついた部分のテキストを格納する
                "title_txt_ja":     meta_info["title"],
                "url_s":            meta_info["url"],
            })

    #solrへ登録を実行
    indexer.load("anno",data)

if __name__=="__main__":
    datastore.connect()
    load_sentence()
    load_affiliation()
    datastore.close()
solrindexer.py
#Solrへデータを登録するプログラム

import json
import urllib.parse
import urllib.request

#使用するsolrのurl
solr_url="http://localhost:8983/solr"
#変数openerはプロキシを環境変数に設定している場合でも動くようにするために定義。
#空のdict{}を渡すことにより環境変数のプロキシ設定を無効にする
opener=urllib.request.build_opener(urllib.request.ProxyHandler({}))

def load(collection,data):
    #collectionはデータ登録先のsolrのコア名、dataは登録するデータをdict型で受け取る
    #solrへデータを登録するためのリクエストを作成
    req=urllib.request.Request(
        url="{0}/{1}/update".format(solr_url,collection),  #urlはsolrのurl+コア名+updateを連結して生成する
        data=json.dumps(data).encode("utf-8"),   #dict型のdataをjson.dumps関数でjson形式の文字列に変換する
        headers={"content-type":"application/json"})   #headerで送信データがjson型式であることを指定

    #データの登録を実行
    with opener.open(req) as res: #変数resでリクエストの返答を受け取る。プロキシ環境でない場合は、opner.openの代わりにurllib.request.urlopenで可
        #データ確認 
        print(res.read().decode("utf-8"))   #utf-8からstr型に変換して受け取る 

    #solrではコミットという行為を実行してデータの登録を行う
    url="{0}/{1}/update?softCommit=true".format(solr_url,collection)
    req=urllib.request.Request(url)
    with opener.open(req) as res:
        print(res.read().decode("utf-8"))


0

3Answer

Comments

  1. @syun_nissi

    Questioner

    ありがとうざいます。
    ご指摘の通り私のコードに間違いがあり、""を削除したところ動きました。
    サンプルコードがあるのをご教示いただき、ありがとうございました。

エラーにHTTP Error 400: Bad Requestとありますので、原因はリクエスト時のURLかJSONのデータかヘッダーにあると思われます。

1Like

Comments

  1. @syun_nissi

    Questioner

    アドバイスいただきありがとうございます。参考書に記載のコードの通り入力しているのは間違いはないので、おそらく誤植があると思われますが、どこなのかがわかっておりません。
    初心者のため、いただいたアドバイスも理解しきれずにいますが、少し試行錯誤して考えてみたいと思います。
    どうもありがとうございました。
  2. デバッガーを使われた方が良いかも知れません。(既に使われていたら、すみません)
    デバッガーを使うと、プログラムを一行ずつ実行でき、変数の中身も確認できるので、どこに原因があるのかを把握できます。

    例:VS CodeでPythonをデバッグする方法
    https://karaage.hatenadiary.jp/entry/2019/02/20/073000


    「HTTP Error 400: Bad Request」はリクエストの内容が正しくなかったことを意味します。

    このプログラムでリクエストを作成しているのはload関数内の下記の二箇所です。

    一箇所目

    req=urllib.request.Request(
    url="{0}/{1}/update".format(solr_url,collection),
    data=json.dumps(data).encode("utf-8"),
    headers={"content-type":"application/json"})

    ここでは変数url、data、headersの中身が正しくなかった可能性があります。

    二箇所目

    req=urllib.request.Request(url)

    ここでは変数urlの中身が正しくなかった可能性があります。
  3. @syun_nissi

    Questioner

    ご丁寧なアドバイスをいただきありがとうございます。
    画像を添付したいので、メッセージ投稿いたします。

さっそくデバッグを試していますが、ソースコードでimportしているsqlitedatastore.pyで「例外が発生しました: OperationalError no such table: docs」というメッセージが出てデバッグが止まってしまいます。sqliteテーブルには確かにdocsテーブルがあるので、なぜテーブルがない、というメッセージが出るのかがわかりません。肝心の該当箇所までデバッグが進みません。

2020_10_19_21_49_17.png

ご指摘いただいた箇所に間違いがないかは自分自身でも確認してみたいと思います。

0Like

Your answer might help someone💌