Yasu777 commited on
Commit
13f095f
·
1 Parent(s): 3a7ba26

Update app.py

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