QA@IT

python の requests を用いた json 形式のフォーム入力

403 PV

初めまして。python 初心者の kazumann1 と申します。
現在python の requests を用いた json 形式のフォーム入力に挑戦しています。

具体的には家計簿サービス MoneyForward(ブラウザ)の支出記録入力フォームを
手動ではなく、ファイルをアップロードして記録を保存するのが目的です。


HTML の該当箇所を掲載致します。

<form id="js-cf-manual-payment-entry-form" data-type="json" action="/user_asset_acts" accept-charset="UTF-8" data-remote="true" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input value="0" type="hidden" name="user_asset_act[is_transfer]" id="user_asset_act_is_transfer" />
<input value="0" type="hidden" name="user_asset_act[is_income]" id="user_asset_act_is_income" />
<div class='js-cf-edit-container pc' style='max-height: 580px;'>
<div class='control-group-left'>
<div class='category-contents'>
<input class="h_l_ctg" type="hidden" name="user_asset_act[large_category_id]" id="user_asset_act_large_category_id" />
<div class='btn-group btn_l_ctg'>
<a class='btn btn-small dropdown-toggle v_l_ctg' data-toggle='dropdown' id='js-large-category-selected'>
未分類
<span class='caret'></span>
</a>
</div>
<input class="h_m_ctg" type="hidden" name="user_asset_act[middle_category_id]" id="user_asset_act_middle_category_id" />
<div class='btn-group btn_m_ctg' id='target-js-content-field'>
<a class='btn btn-small dropdown-toggle v_m_ctg' data-toggle='dropdown' id='js-middle-category-selected'>
未分類
<span class='caret'></span>
</a>
</div>
</div>
<div class='right-column'>
<input id="js-cf-manual-payment-entry-amount" placeholder="金額を入力してください" class="payment-amount" autocomplete="off" type="text" name="user_asset_act[amount]" />
<span class='payment-unit'></span>
</div>
</div>
<div class='control-group-right'>
<input id="js-cf-manual-payment-entry-updated-at" type="hidden" name="user_asset_act[updated_at]" />
<div class='input-date'>
<p data-date-format='yyyy/mm/dd' data-date='2019/06/26' id='js-cf-manual-payment-entry-calendar'>
日付
<span id='js-cf-manual-payment-entry-updated-at-label'></span>
<i class='icon-calendar'></i>
</p>
</div>
<div class='source-container'>
<input value="0" type="hidden" name="user_asset_act[sub_account_id_hash]" id="user_asset_act_sub_account_id_hash" />
</div>
</div>
<div class='control-group'>
<div class='right-column'>
<input id="js-cf-manual-payment-entry-content" placeholder="内容を入力してください(任意)" class="align-left" type="text" name="user_asset_act[content]" />
<!--[if lte IE 9]>
(内容を入力してください)
<![endif]-->
</div>
</div>
</div>
<div class='submit-box'>
<input type="submit" name="commit" value="保存する" class="btn btn-success" style="width: 120px; height: 33px;" id="js-cf-manual-payment-entry-submit-button" data-disable-with="保存する" />
<img style="display:none;" id="js-cf-manual-payment-entry-loading-image" src="/assets/loading-27a69b744b2ab154dcfe222f588a1235cf36f59242407c350370346125d392e0.gif" />
</div>
</form>


これに対し、下記のコードを書いてみました。
結果、{"status":422,"error":"Unprocessable Entity"} とのことです。

def cf_manual_entry(self):

    ses = self.sign_in_to_mf()
    urllib3.disable_warnings()

    headers = {'Accept': 'application/json', 'Content-Type': 'application/json'}

    cf_entry_form = {
        'user_asset_act[is_transfer]': '0',
        'user_asset_act[is_income]': '0',
        'user_asset_act[large_category_id]': '21', #交際費
        'user_asset_act[middle_category_id]': '44', #飲み会
        'user_asset_act[amount]': '123',
        'user_asset_act[updated_at]': '2019/06/07',
        'user_asset_act[sub_account_id_hash]': '0',
        'user_asset_act[content]': 'TEST',
    }

    cf_entry_form = json.dumps(cf_entry_form).encode('utf8')
    post = ses.post(self.mf + '/user_asset_acts', data = cf_entry_form, headers = headers)

    print(post.headers['Content-Type'])
    print(post.text)

application/json; charset=utf-8
{"status":422,"error":"Unprocessable Entity"}

sign_in_to_mf() は ログイン後の requests.Session() です。
Content-Type は意図した通り、application/json へと変更されています。

422 Error は不適合なフォーム形式が起因らしいですが、
各項目の format は確認済みなので手詰まりです。

上記フォーム・コードのみでははっきりとしない箇所もあるかと思いますが、
もし何か見落としているものがあればご指摘頂けますと幸いです。

長文失礼しました。よろしくお願いします。

ウォッチ

この質問への回答やコメントをメールでお知らせします。