Yasu777 commited on
Commit
38ce015
·
1 Parent(s): 0ec16c8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -78
app.py CHANGED
@@ -2,7 +2,6 @@ import streamlit as st
2
  import os
3
  import subprocess
4
  from urllib.parse import urlparse
5
- import warnings
6
  from bs4 import BeautifulSoup
7
  import re
8
  from tinydb import TinyDB, Query
@@ -11,11 +10,13 @@ import urllib.request
11
  import urllib.error
12
  import datetime
13
 
14
- @st.cache_resource
15
  def get_top_urls_and_keyword(keyword):
 
16
  GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
17
  CUSTOM_SEARCH_ENGINE_ID = os.getenv("CUSTOM_SEARCH_ENGINE_ID")
18
 
 
19
  service = build("customsearch", "v1", developerKey=GOOGLE_API_KEY)
20
  response = service.cse().list(
21
  q=keyword,
@@ -25,9 +26,12 @@ def get_top_urls_and_keyword(keyword):
25
  start=1
26
  ).execute()
27
 
 
28
  urls = [item['link'] for item in response["items"][:3]]
 
29
  return urls, keyword
30
 
 
31
  def get_valid_url(urls):
32
  for url in urls:
33
  try:
@@ -35,6 +39,7 @@ def get_valid_url(urls):
35
  charset = response.headers.get_content_charset()
36
  html = response.read().decode(charset)
37
  soup = BeautifulSoup(html, "html.parser")
 
38
  if is_japanese_text(soup.get_text()):
39
  return url
40
  except urllib.error.URLError as e:
@@ -43,69 +48,85 @@ def get_valid_url(urls):
43
  print(f"HTTPエラー: {e.code}")
44
  except:
45
  print("予期せぬエラーが発生しました。")
 
46
  return None
47
 
 
48
  def is_japanese_text(text):
 
49
  japanese_pattern = r"[\p{Hiragana}\p{Katakana}\p{Han}ー〜、。「」【】]"
50
  return bool(re.search(japanese_pattern, text))
51
 
52
- def is_valid_html(html):
53
- with warnings.catch_warnings(record=True) as w:
54
- warnings.simplefilter('always')
55
- BeautifulSoup(html, 'html.parser')
56
- return len(w) == 0
57
 
 
58
  db = TinyDB("db.json")
 
 
59
  current_time = datetime.datetime.now()
60
  one_day_ago = current_time - datetime.timedelta(days=1)
 
 
61
  db.remove(Query().timestamp.test(lambda x: datetime.datetime.fromisoformat(x) <= one_day_ago))
62
 
63
- st.title("記事生成ウェブアプリ")
64
- st.write("このアプリは、与えられたキーワードを使用して記事を生成します。")
 
65
 
 
66
  new_keyword = st.text_input("キーワード:")
 
 
67
  keyword_id = re.sub(r"\W+", "", new_keyword) if new_keyword else None
68
 
 
69
  last_keyword = db.search(Query().keyword_id.exists())
70
 
71
  if new_keyword and (not last_keyword or last_keyword[0]['keyword_id'] != keyword_id):
 
 
72
  if last_keyword:
73
  db.remove(Query().keyword_id == last_keyword[0]['keyword_id'])
 
74
  with open("output1.txt", "w") as f:
75
  f.write("")
76
  with open("output2.txt", "w") as f:
77
  f.write("")
78
  with open("output3.txt", "w") as f:
79
  f.write("")
 
80
  for i in range(1, 4):
81
  filename = f"output0-{i}.txt"
82
  if os.path.exists(filename):
83
  os.remove(filename)
84
-
 
85
  if new_keyword:
86
  urls, keyword = get_top_urls_and_keyword(new_keyword)
87
- if len(urls) < 3:
88
  st.error("Google検索の結果が3つ未満です。別のキーワードを試してみてください。")
89
  else:
90
  url1, url2, url3 = urls
91
 
92
- if keyword_id:
93
- output1 = st.empty()
94
- output2 = st.empty()
95
- output3 = st.empty()
 
96
 
97
- result = db.search((Query().name == "output2.txt") & (Query().keyword_id == keyword_id))
98
- if result:
99
- editable_output2 = result[0]["content"]
100
- else:
101
- editable_output2 = ""
 
102
 
103
- if st.button("記事構成作成", key=f"run_button_{keyword_id}"):
104
- try:
105
  with st.spinner("タイトル・見出し作成中..."):
106
  urls, keyword = get_top_urls_and_keyword(new_keyword)
107
  url1, url2, url3 = urls
108
 
 
109
  parsed_urls = [urlparse(url) for url in urls]
110
  if len(urls) != len(set(urls)):
111
  st.error("異なるURLを入力してください。")
@@ -114,20 +135,17 @@ if keyword_id:
114
  st.error("異なるサイトのURLを入力してください。")
115
  st.stop()
116
 
117
- process = subprocess.Popen(["python3", "first.py", url1, url2, url3])
118
- process.wait()
119
 
120
  with open("output1.txt", "r", encoding="utf-8") as f:
121
  content = f.read()
 
122
  content = re.sub(r"\n関連するテキスト部分:.*", "", content, flags=re.DOTALL)
123
  output1.text(content)
124
  db.upsert({"name": "output1.txt", "content": content, "keyword_id": keyword_id},
125
- (Query().name == "output1.txt") & (Query().keyword_id == keyword_id))
126
-
127
- with st.spinner("その他の処理を実行中..."):
128
- process = subprocess.Popen(["python3", "second.py", keyword])
129
- process.wait()
130
 
 
131
  with open("output2.txt", "r", encoding="utf-8") as f:
132
  editable_output2 = f.read()
133
  soup = BeautifulSoup(editable_output2, "html.parser")
@@ -146,63 +164,47 @@ if keyword_id:
146
  )
147
 
148
  st.success("処理が完了しました。")
149
- except subprocess.CalledProcessError:
150
- st.error("記事の構成作成中にエラーが発生しました。もう一度お試しください。")
151
- except Exception as e:
152
- st.error(f"予期せぬエラーが発生しました:{str(e)}")
153
 
154
- editable_output2 = st.text_area("output2.txtを編集してください:", value=editable_output2)
 
155
 
156
- if st.button("記事作成"):
157
- with st.spinner("記事作成中..."):
158
- # 編集済みの "output2.txt" の内容をデータベースに保存
159
- existing_docs = db.search((Query().name == "output2.txt") & (Query().keyword_id == keyword_id))
160
- if existing_docs:
161
- db.update({"content": editable_output2}, doc_ids=[doc.doc_id for doc in existing_docs])
 
162
 
163
- # データベースから読み込んだ "output2.txt" の内容をファイルに書き込む処理
164
- with open("output2.txt", "w", encoding="utf-8") as f:
165
- f.write(editable_output2)
166
-
167
- process = subprocess.Popen(
168
- ["python3", "third.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
169
- )
170
- stdout, stderr = process.communicate()
171
- process.wait()
172
- if stderr:
173
- st.error(f"エラー: {stderr.decode('utf-8')}")
174
- if stdout: # この部分を追加してください。
175
- st.info(f"情報: {stdout.decode('utf-8')}")
176
- if os.path.exists("output3.txt"):
177
- with open("output3.txt", "r", encoding="utf-8") as f:
178
- output3_content = f.read() # output3.txt の内容読み込み
179
- output3.text(output3_content) # 元のテキスト表示
180
- st.text_area("output3.txtの内容(コピー用):", value=output3_content, height=200, key="output3_text_area") # テキストエリアに表示
181
- else:
182
- st.write("output3.txt が見つかりません。third.py が正常に実行されていることを確認してください。")
183
-
184
- if st.button("保存"):
185
- h2_limit = 5
186
- h3_limit = 10
187
-
188
- soup = BeautifulSoup(editable_output2, "html.parser")
189
- h2_count = len(soup.find_all("h2"))
190
- h3_count = len(soup.find_all("h3"))
191
-
192
- if h2_count > h2_limit or h3_count > h3_limit:
193
- st.error(f"h2タグの数が{h2_limit}を、h3タグの数が{h3_limit}を超えています。")
194
- elif not is_valid_html(editable_output2):
195
- st.error("入力されたテキストは正しいHTML形式ではありません。")
196
- else:
197
  content = editable_output2
198
  with open("output2.txt", "w", encoding="utf-8") as f:
199
  f.write(content)
200
  db.upsert({"name": "output2.txt", "content": content, "timestamp": current_time.isoformat(),
201
- "keyword_id": keyword_id}, (Query().name == "output2.txt") & (Query().keyword_id == keyword_id))
202
  st.write("output2.txt に変更が保存されました。")
203
 
204
- if st.button("データクリア"):
205
- db.remove(Query().keyword_id == keyword_id)
206
- st.write("データベースがクリアされました。")
 
207
  else:
208
  st.warning("キーワードを入力してください。")
 
2
  import os
3
  import subprocess
4
  from urllib.parse import urlparse
 
5
  from bs4 import BeautifulSoup
6
  import re
7
  from tinydb import TinyDB, Query
 
10
  import urllib.error
11
  import datetime
12
 
13
+ @st.cache
14
  def get_top_urls_and_keyword(keyword):
15
+ # SecretsからGoogle APIキーとカスタム検索エンジンIDを取得
16
  GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
17
  CUSTOM_SEARCH_ENGINE_ID = os.getenv("CUSTOM_SEARCH_ENGINE_ID")
18
 
19
+ # Google Customサーチ結果を取得
20
  service = build("customsearch", "v1", developerKey=GOOGLE_API_KEY)
21
  response = service.cse().list(
22
  q=keyword,
 
26
  start=1
27
  ).execute()
28
 
29
+ # 上位3つのサイトURLを取得
30
  urls = [item['link'] for item in response["items"][:3]]
31
+
32
  return urls, keyword
33
 
34
+
35
  def get_valid_url(urls):
36
  for url in urls:
37
  try:
 
39
  charset = response.headers.get_content_charset()
40
  html = response.read().decode(charset)
41
  soup = BeautifulSoup(html, "html.parser")
42
+ # 抽出したテキストが日本語であるかどうかを判定
43
  if is_japanese_text(soup.get_text()):
44
  return url
45
  except urllib.error.URLError as e:
 
48
  print(f"HTTPエラー: {e.code}")
49
  except:
50
  print("予期せぬエラーが発生しました。")
51
+
52
  return None
53
 
54
+
55
  def is_japanese_text(text):
56
+ # 日本語のテキストであるかどうかを判定する条件を定義
57
  japanese_pattern = r"[\p{Hiragana}\p{Katakana}\p{Han}ー〜、。「」【】]"
58
  return bool(re.search(japanese_pattern, text))
59
 
 
 
 
 
 
60
 
61
+ # データベースへの接続を確立
62
  db = TinyDB("db.json")
63
+
64
+ # 1日前のタイムスタンプを取得
65
  current_time = datetime.datetime.now()
66
  one_day_ago = current_time - datetime.timedelta(days=1)
67
+
68
+ # データベースから1日前のタイムスタンプ以前のログを削除
69
  db.remove(Query().timestamp.test(lambda x: datetime.datetime.fromisoformat(x) <= one_day_ago))
70
 
71
+ # タイトルと説明
72
+ st.title("Baby Writer")
73
+ st.write("これは、与えられたキーワードを使用して生成します。")
74
 
75
+ # キーワード入力
76
  new_keyword = st.text_input("キーワード:")
77
+
78
+ # キーワードごとにデータを保存するための識別子
79
  keyword_id = re.sub(r"\W+", "", new_keyword) if new_keyword else None
80
 
81
+ # データベースから前回のキーワードを取得
82
  last_keyword = db.search(Query().keyword_id.exists())
83
 
84
  if new_keyword and (not last_keyword or last_keyword[0]['keyword_id'] != keyword_id):
85
+
86
+ # キーワードが変更された場合は、データベースから前回の結果を削除
87
  if last_keyword:
88
  db.remove(Query().keyword_id == last_keyword[0]['keyword_id'])
89
+ # output1.txt、output2.txt、output3.txtの内容をクリアする
90
  with open("output1.txt", "w") as f:
91
  f.write("")
92
  with open("output2.txt", "w") as f:
93
  f.write("")
94
  with open("output3.txt", "w") as f:
95
  f.write("")
96
+ # output0-1.txt、output0-2.txt、output0-3.txtを削除する
97
  for i in range(1, 4):
98
  filename = f"output0-{i}.txt"
99
  if os.path.exists(filename):
100
  os.remove(filename)
101
+
102
+ # 新しいキーワードが入力されたときにGoogle検索を行う
103
  if new_keyword:
104
  urls, keyword = get_top_urls_and_keyword(new_keyword)
105
+ if len(urls) < 3: # Google検索の結果が3つ以上であることを確認
106
  st.error("Google検索の結果が3つ未満です。別のキーワードを試してみてください。")
107
  else:
108
  url1, url2, url3 = urls
109
 
110
+ if keyword_id: # キーワードIDが存在することを確認
111
+ # 出力欄
112
+ output1 = st.empty()
113
+ output2 = st.empty()
114
+ output3 = st.empty()
115
 
116
+ # データベースから編集済みの "output2.txt" を読み込む処理を追加
117
+ result = db.search((Query().name == "output2.txt") & (Query().keyword_id == keyword_id))
118
+ if result:
119
+ editable_output2 = result[0]["content"]
120
+ else:
121
+ editable_output2 = ""
122
 
123
+ # runボタン
124
+ if st.button("構成作成", key=f"run_button_{keyword_id}"):
125
  with st.spinner("タイトル・見出し作成中..."):
126
  urls, keyword = get_top_urls_and_keyword(new_keyword)
127
  url1, url2, url3 = urls
128
 
129
+ # 重複チェックと同じサイト内のページチェック
130
  parsed_urls = [urlparse(url) for url in urls]
131
  if len(urls) != len(set(urls)):
132
  st.error("異なるURLを入力してください。")
 
135
  st.error("異なるサイトのURLを入力してください。")
136
  st.stop()
137
 
138
+ subprocess.run(["python3", "first.py", url1, url2, url3])
 
139
 
140
  with open("output1.txt", "r", encoding="utf-8") as f:
141
  content = f.read()
142
+ # "関連するテキスト部分:"とそれ以降の部分を削除
143
  content = re.sub(r"\n関連するテキスト部分:.*", "", content, flags=re.DOTALL)
144
  output1.text(content)
145
  db.upsert({"name": "output1.txt", "content": content, "keyword_id": keyword_id},
146
+ (Query().name == "output1.txt") & (Query().keyword_id == keyword_id)) # データベースに結果を保存
 
 
 
 
147
 
148
+ subprocess.run(["python3", "second.py", keyword])
149
  with open("output2.txt", "r", encoding="utf-8") as f:
150
  editable_output2 = f.read()
151
  soup = BeautifulSoup(editable_output2, "html.parser")
 
164
  )
165
 
166
  st.success("処理が完了しました。")
 
 
 
 
167
 
168
+ # 編集欄を表示、編集後の内容をeditable_output2に更新
169
+ editable_output2 = st.text_area("output2.txtを編集してください:", value=editable_output2)
170
 
171
+ # run2ボタン
172
+ if st.button("本文作成"):
173
+ with st.spinner("本文作成中..."):
174
+ # 編集済みの "output2.txt" の内容をデータベースに保存
175
+ existing_docs = db.search((Query().name == "output2.txt") & (Query().keyword_id == keyword_id))
176
+ if existing_docs:
177
+ db.update({"content": editable_output2}, doc_ids=[doc.doc_id for doc in existing_docs])
178
 
179
+ # データベースから読み込んだ "output2.txt" の内容をファイルに書き込む処理
180
+ with open("output2.txt", "w", encoding="utf-8") as f:
181
+ f.write(editable_output2)
182
+
183
+ process = subprocess.Popen(
184
+ ["python3", "third.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
185
+ )
186
+ stdout, stderr = process.communicate()
187
+ process.wait()
188
+ if stderr:
189
+ st.write(f"エラー: {stderr.decode('utf-8')}")
190
+ if os.path.exists("output3.txt"):
191
+ with open("output3.txt", "r", encoding="utf-8") as f:
192
+ output3.text(f.read())
193
+ else:
194
+ st.write("output3.txt が見つかりません。third.py が正常に実行されていること確認してください。")
195
+
196
+ # 保存ボタン
197
+ if st.button("保存"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  content = editable_output2
199
  with open("output2.txt", "w", encoding="utf-8") as f:
200
  f.write(content)
201
  db.upsert({"name": "output2.txt", "content": content, "timestamp": current_time.isoformat(),
202
+ "keyword_id": keyword_id}, (Query().name == "output2.txt") & (Query().keyword_id == keyword_id)) # データベースに変更を保存
203
  st.write("output2.txt に変更が保存されました。")
204
 
205
+ # クリアボタン
206
+ if st.button("データクリア"):
207
+ db.remove(Query().keyword_id == keyword_id)
208
+ st.write("データベースがクリアされました。")
209
  else:
210
  st.warning("キーワードを入力してください。")