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

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

新規登録して質問してみよう
ただいま回答率
85.48%
スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

458閲覧

自分で作ったPythonのプログラムをJinjaで反映させたい

chario

総合スコア2

スクレイピング

スクレイピングとは、公開されているWebサイトからページ内の情報を抽出する技術です。

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/07/23 13:11

編集2021/07/23 16:19

前提・実現したいこと

私は今学校でPythonを勉強してます。
元々Tkinterで作ったプログラムを発表したところWebアプリ化してみたら勉強になるといわれFlask(ローカルのみ)で実装しようとしています。
Jinja自体初めてで、Webサーバー等不慣れな点もたくさんあるため、アドバイスを頂ければと思っています。
あまり回りにPythonの事で相談できる人が少ないのでここで質問をさせてください。

実装したいプログラム

これらをJinjaで実装する場合、どういった書き方(?)等が理想なのでしょうか?
サーバーサイド側の知識があまりなく今まで書いたこともなかったので、どうしていいか混乱してしまっている状態です。
正直Tkinterで作っていたプログラムをJinjaにどうやって落とし込めばいいのか・・・。
大混乱中なため、どんなことでもアドバイスを頂ければ・・・!と思ってます。
宜しくお願い致します。

以下のソースは元々画像をスクレイピングで保存をする というプログラムの一部になります。
全文載せてしまうと長ったらしいので割愛させて頂きます。

python

1###スクレイピング・データ書き出し・フォルダ指定・作成・変換関数 2def url_get(): 3 counter = 1 4 url = txb.get() 5 html = requests.get(url) 6 soup = BS(html.content, "html.parser") 7 directory = Path(input_text.get() + "/original") 8 os.makedirs(directory, exist_ok=True) 9 for element in soup.find_all("img"): 10 src = element.get("src") 11 if src is None: 12 continue 13 image_url = urllib.parse.urljoin(url, src) 14 print(image_url) 15 imgdata = requests.get(image_url) 16 file_name = image_url.split("/")[-1] 17 if not file_name.endswith((".jpg", ".jpeg", ".png", ".gif")): 18 txt = file_name.find("?") 19 file_name = (file_name[:txt]) 20 print(file_name) 21 file_name = (str(counter) + "_" + file_name) 22 out_path = directory.joinpath(file_name) 23 with open(out_path, mode="wb") as f: 24 a = f.write(imgdata.content) 25 counter += 1 26 time.sleep(0.5) 27 print(file_name) 28 print("finish!!!!") 29 30

該当のソースコード

jinjaで実装しようとしているもの
URLを入れると画像を出す という流れにしたいと思っています。

python

1app = Flask(__name__) 2@app.route("/top", methods=["GET"]) 3def input(): 4 return render_template("input.html", title="TOP") 5@app.route("/", methods=["POST"]) 6def output(): 7 counter = 1 8 name = request.form.get("name") 9 URL = requests.get(name) 10 soup = BS(URL.content, "html.parser") 11 directory = Path("./static/gazou") 12 os.makedirs(directory, exist_ok=True) 13 for element in soup.find_all("img"): 14 src = element.get("src") 15 image_url = urllib.parse.urljoin(URL, src) 16 imgdata = requests.get(image_url) 17 file_name = image_url.split("/")[-1] 18 if not file_name.endswith((".jpg", ".jpeg", ".png", ".gif")): 19 txt = file_name.find("?") 20 file_name = (file_name[:txt]) 21 file_name = (str(counter) + "_" + file_name) 22 out_path = directory.joinpath(file_name) 23 with open(out_path, mode="wb") as f: 24 a = f.write(imgdata.content) 25 counter += 1 26 time.sleep(0.5) 27 return render_template("output.html", name=name, title = "jinja難しい!!!") 28 29@app.route("/upload") 30def upload(): 31 return render_template("upload.html") 32 33###locakhost起動 34if __name__ == "__main__": 35 app.run(port=8080, debug=True, host='localhost') 36

エラーで引っかかってしまうところ

TypeError: Cannot mix str and non-str arguments
image_url = urllib.parse.urljoin(URL, src)

補足情報(FW/ツールのバージョンなど)

VScodeで書いてます。
htmlやCSSも別途で書いてます。
Python 3.9.4 です。
何もかもがゴリゴリの初心者です。

###追記(HTMLファイル)
base.html

html

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <link rel="stylesheet" href="../static/CSS/style.css"> 7 <title>{{ title }}</title> 8</head> 9<body> 10 <h1>ここが変換ベース?</h1> 11 <p>{{file_name}}</p> 12 {% block content %} 13<!-- ここに変換部分が挿入される?? --> 14 15 {% endblock %} 16</body> 17</html> 18

input.html

html

1 2{% extends "base.html" %} 3{% block content %} 4<form action="/top" method="GET" enctype="multipart/form-data"> 5 <input type="url" id="url" name="URL" placeholder="URLを入力"> 6 <input class="submit-button" value="実行" type="submit"> 7</form> 8{% endblock %}

output.html

html

1{% extends "base.html" %} 2{% block content %} 3<p>{{ name }}</p> 4<p>{{ URL }}</p> 5<p>{{ html }}</p> 6<h1>あうとぷっとだよ!!</h1> 7<a href="/top">back top</a> 8{% endblock %}

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

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

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

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

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

guest

回答1

0

ベストアンサー

エラーの内容がCannot mix str and non-str arguments
つまり文字列と文字列でないものを組み合わせることはできないと出ています。

みたところsrcは文字列ですがURLはrequests.getのレスポンスオブジェクトになっているため
上記のエラーが出ているのだと思います。

原因は実装したいプログラムのプログラムから該当のソースコードへ書き換える際に、
変数名を変更したことではないでしょうか。

Python

1URL = request.form.get("name") 2html = requests.get(URL) 3soup = BS(html.content, "html.parser")

とすると変数名とデータの内容の齟齬がなくなりわかりやすくなるのではないでしょうか。

投稿2021/07/23 13:42

Alma-field

総合スコア108

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

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

chario

2021/07/23 14:34

なるほど!ありがとうございます! 確かに書き換えました…。 おっしゃられている通りに書き直した所、エラー自体は吐かなくなったもののブラウザ側で「Method Not Allowed」405エラーが出てしまいした…。 FlaskやJinjaではこういったスクレイピング処理や画像を出す処理なんかは難しいのでしょうか?
Alma-field

2021/07/23 14:49

HTMLファイルの中身がわからないので具体的なアドバイス等はできませんが... `405 Method Not Allowed`というエラーは 例えば`@app.route("/top", methods=["GET"])`としたページへ postアクセス(フォームを送信)した場合などに出るものだと思います。 ですのでhtml内のform-actionの指定が間違っているなどの原因が考えられます。 405エラーが発生するのはどの状況で発生するのでしょうか。 例:「最初に/topのページへアクセスしたとき」「/topのページからformを送信したとき」など 教えていただけると何らかのアドバイスができるかもしれません。 また、Flaskを用いてブラウザに画像を表示することはそこまで難しいものではないと思います。
chario

2021/07/23 16:46

確認してみました! 追記でHTMLファイルを載せてみました。 input.htmlのmethodが[POST]だったのを[GET]に変更したところ405エラーを回避することができました!!もう一度POST/GETについてちゃんと勉強します! 画像表示をさせよう・・・と思ったのですが、そもそもスクレイピングの処理部分が動いていない事に気づきました。input部分にURLを入力し実行ボタンをおすと、output.htmlに行くかと思いきや、input.htmlにとどまったまま…。もう何が何やら…w Tkinterで関数を動かしたいときは[command=関数名]を起爆剤のようにして動かしていたのですが、Flask・Jinjaの場合はどのように関数を動かすのでしょうか?? たくさんわからない事だらけで…助けてくれえええええええええ!!!!!!!!!!
Alma-field

2021/07/23 17:40

input.html内の <form action="/top" method="GET" enctype="multipart/form-data"> の部分を以下のように変えるとoutput.htmlのページへ移動できると思います。 <form action="/" method="POST" enctype="multipart/form-data"> ページが移動しなかった原因は formタグの中のactionの値が送信先のURLを指定するもので、 ここが/top(input.htmlが表示されるパス)のままになっているからです。 pythonプログラムの中の @app.route("/", methods=["POST"]) def output(): の部分が"/"パスに"POST"リクエストされた場合に outputを実行するという意味になります。 @app.routeで指定したパスと同じものを formタグのactionの値として指定すれば任意のページに送ることができます。
chario

2021/07/24 02:27

なるほど!自分でinput.htmlのaction部分を固定してしまっていたが為に動かなかった。という事なんですね・・・。 動かしたい部分のルートの"/"と、method部分をpythonファイルとhtmlで紐づけするために、一緒にする必要がある。 その部分を修正して、 name = request.form.get("name") 部分が旨くURLを受け取る事ができなかったのでURL = request.form["URL"]と変更したところ無事にプログラムが動きました!!!!!! めちゃくちゃ感動しずぎてまじで泣きそう!! 最初から最後まで本当に丁寧に教えてくださってありがとうございます! もう少し手を入れてちゃんと見栄えの良いものにしたいと思います!ありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問