上流SEが久しぶりに開発してみる日記

マネジメント専任システムエンジニアがなれないプログラミングをしてみる日記です。

Go言語でpythonで作成したjsonを取得できない

GO言語で画面を作っているのですが、GCFで作ったJsonをGCS経由で表示しようとしています。

 

先日の記事のJsonpythonのlines指定で作成したところ、GO言語の画面側で取得できなかったです。

 

■Go言語側のロジック

    //GCSから取得
    b := GetDataFromGCS("shiawase""shiawaselog.json", req)
    c := byte(b)
    var result shiawaseloglist
    err := json.Unmarshal(byte(c), &result)
    fmt.Println(result)
    if err != nil {
        fmt.Println("umvarshal")
        fmt.Println(err)
    }
 
Unmarshalでエラーとなります。
 
■エラー内容
umvarshal
invalid character '{' after top-level value
 
 
■インプットファイル
こんな感じのlines=Trueで作ったファイル
{"a":1,"b":2,"c":3}
{"a":1,"b":2,"c":3}
 
 
対処がわからなかったので、インプットファイルをlines=Falseで作成したファイルに変えたら
うまくいきました。
 
 
■修正後インプットファイル
[{"a":1,"b":2,"c":3},{"a":1,"b":2,"c":3}]
 

python データフレームでjsonを扱うときのlines指定

jsonをデータフレーム変換するときに、ぶつかりました。

 

jsonファイルって複数データになるとlines指定しないととても見づらい。

なのでlines指定をすると改行されて見やすくなります。

 

コマンド lines指定有り

df_lines.to_json('df_lines.json',orient = 'records')

 

結果

{"a":1,"b":2,"c":3}
{"a":1,"b":2,"c":3}

 

コマンド lines指定なし

df_lines.to_json('df.json',orient = 'records',lines=True)

 

結果

[{"a":1,"b":2,"c":3},{"a":1,"b":2,"c":3}]

 

 

lines指定で出力したjsonファイルを読み込むところでは、

read_jsonでlines指定しないと落ちます。

 

ここに気付くのに時間がかかりました。

よしなには読み込んでくれないんですね。。。。

 

■OKパターン

import pandas as pd
import numpy as np

input_lines = '{"a":"1","b":"2","c":"3"}\n{"a":"1","b":"2","c":"3"}'
df_lines = pd.read_json(input_lines, orient='records',lines=True)

 

■NGパターン

import pandas as pd
import numpy as np

input_lines = '{"a":"1","b":"2","c":"3"}\n{"a":"1","b":"2","c":"3"}'
df_lines = pd.read_json(input_lines, orient='records')

 

 

インプットとするjsonがlines指定でできあがっているのであれば、read_jsonでもちゃんとlines指定しましょうって話ですね。

 

GAEでWEBアプリケーションを作る(Google Cloud Storageへアクセス)

GAEでWEBアプリケーションを作って、

作ったWEB画面にGoogle Clund Storageにあるデータを表示するところで躓きました。

 

こんな感じで、Storageのファイルにアクセスしてテキストを返す関数を作りました。

 

//GCSからデータ取得
func GetData(bucketname string, filename string, r *http.Request) string {

ctx := appengine.NewContext(r) // Contextの作成
clinet, err := storage.NewClient(ctx)
if err != nil {
エラー処理
}

reader, err := clinet.Bucket(bucketname).Object(filename).NewReader(ctx)
if err != nil {
エラー処理
}

b, err := ioutil.ReadAll(reader)
if err != nil {
エラー処理
}

return string(b)
}

 

だが動かない。

 

そうSDKのインストールができていませんでした。

 

CLOUD SHELLから

 

go get -u cloud.google.com/go/storage

 

を実行するとSDKがインストールできて動きましたー。

 

 

 

jsonデータがなんかおかしい

一瞬焦った話です。

 

 

Google Cloud上にアプリケーションのせてjsonファイルにデータを累積しています。

 

データはこんな感じ

 

{"データ日付":"2021\/10\/12","値":"100","前日差分":10.0}
{"データ日付":"2021\/10\/11","値":90,"前日差分":0.0}
{"データ日付":"2021\/10\/8","値":90,"前日差分":10.0}

 

あれ?

 

よく見ると1行目の値とそれ以降の値が違う?

 

2行目の

90,"

 

ここだけ見ると文字列の最後に変なカンマ入っている?

 

過去分の値使って計算しているロジックが全部死んでる?

 

 

ってかなりあせりました。

 

よく見ると

90,で区切られていて、単純にこれは数値型ってことですね。

 

だから計算自体はできてると思われる。。。

 

むしろ1行目だけ値が文字列になっているから"100",カンマが外にあるように見えているだけですね。

 

でもなんで1行目だけ文字列なんだろう。

 

よく見ると

 

1行目は当日の値をスクレイピングして取ってきます。

その時.textでstringにしてました。

 

一方でそれより前の明細は、GCPのストレージに累積しているjsonファイルをとってきているだけ。

 

特に何も指定していないのですが、おそらくここですべてが数値になっている。

 

この過去分データと当日のスクレイピングした1明細をデータフレームでがっちゃんこしているので、1行目(当日の明細)だけ文字列になっているという仕組みですね。

 

なんかきもちわるいんで直しておきますか。。。

 

スクレイピングした明細も数値変換しておきましょう。

 

 

あー計算が全部死んでいると思って焦ったー。

python データフレームのデータをfor文で1件ずつ処理したい

データフレームのデータを1件ずつ処理したいのですが、

データフレームを行指定してデータを取得する必要があります。

 

今回は指定した行だけで完結せずに前後の行も参照しながら処理をしたいです。

 

 

 

調べてみるとやり方はいっぱいありそう。

 

 

汚いけどこんな感じで動きました。

ilocを使うと行番号を指定して、対象行を抽出できます。

locは行ラベル指定みたいですね。

 

import pandas as pd

#差分計算
sabun = []
for i in range(len(df)-1):
sabun.append(int(df['値'].iloc[i]-df['値'].iloc[i+1]))

 

 

dfを1件ずつ処理しています。

差分を取得するために、ilocで行を指定して計算して差分を取得して配列に入れています。

 

調べてみるともっとスマートな扱い方がありそうですが、

いったんこれで十分動いたので問題ないかと思います。

 

python seleniumでクリックできない!

pythonseleniumを動かしています。

 

また躓いたので共有。

 

ajaxとかjavascriptごりごりのサイトだと簡単にクリックできない場合があります。

 

だいたいは、

 

driver.find_element_by_xpath('パス').click()

 

こんな感じでいけるんですが、クリックできないという話です。

 

 

今回出会ったサイトは、画面が上下の窓に分かれているサイトで、

ボタンを押すとポップアップウインドウがでる。

 

そして押したいボタンが表示範囲外に出てくるサイト。

 

まあ、こんな構成にしたら簡単には操作できないよね。

 

むしろエンジニアとしてこういうサイトは作るなってことですね。

 

個人的には心当たりあるので反省。。。

 

 

でいろいろ調べるとonclickイベントに書かれているjavascriptを直接実行できるので、

それで代替できるとのこと。

 

driver.execute_script('onclickに記載されているjavascriptをそのまま転記')

 

こんな感じ。

 

やってみたらうまくできました。

 

ふ~。

 

やはりサイトはシンプルに作るのが、作り手にとっても利用者にとっても一番いいよねということだと思いました。

python selenium でテキストボックス先頭に0が入る。

また、しょうもないミスの話。

 

seleniumでテキストボックスに数字を入れようとするとどうしても

先頭に0が入る。

 

何を調べもダメ。。。

 

コードはこう。

 

nedan1.send_keys('数字')

 

絶対あっている。

 

 

よく動きを見ると、

 

あれ・・・・

 

画面表示したときに初期値0が入っている。

 

 

なるほど。

 

nedan1.clear()

nedan1.send_keys('数字')

 

で解決しました。

 

send_keysは今ある値の後ろに追加しにいくのですね。

だから初期値の0が残っていたと。。

 

0をクリアしてからsend_keysでOKでした。

 

なんというしょうもなさ。。。