From ec8ec7fbad9e66d57954a47f6455a2049d5d56c9 Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 21:03:35 +0900 Subject: [PATCH 01/11] =?UTF-8?q?=F0=9F=94=A7=20(#2)[docs]=20README?= =?UTF-8?q?=E3=81=AE=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89=E3=83=A9=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E4=BE=8B=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 出力ファイル拡張子の指定方法を明確化。`.txt`の形式で統一して記載するよう修正しました。 - スクレイピングコマンド例にファイル拡張子の誤りがあり、`.txt` とするのが適切であったため、これを修正。 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 18714a5..7a7930a 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ PEGASUSをコマンドラインから使用するには、以下のようなコ ```shell # 単一のURLからスクレイピングを開始 🌐 -pegasus --base-url https://example.com/start-page output_directory --exclude-selectors header footer nav --include-domain example.com --exclude-keywords login --output-extension txt +pegasus --base-url https://example.com/start-page output_directory --exclude-selectors header footer nav --include-domain example.com --exclude-keywords login --output-extension .txt # 探索深度を指定して実行 🔍 pegasus --base-url https://docs.eraser.io/docs/what-is-eraser output/eraser_docs2 --exclude-selectors header footer nav aside .sidebar .header .footer .navigation .breadcrumbs --include-domain docs.eraser.io --exclude-keywords login --output-extension .txt --max-depth 2 From a6b1b09e7c523ce00931573b021f48d0e2fe9ff0 Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 22:42:24 +0900 Subject: [PATCH 02/11] =?UTF-8?q?=F0=9F=93=84=20(#2)[feat]=20=E3=82=B9?= =?UTF-8?q?=E3=82=AF=E3=83=AC=E3=82=A4=E3=83=94=E3=83=B3=E3=82=B0=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E3=82=92=E6=8B=A1=E5=BC=B5=E3=81=97=E3=80=81=E6=A4=9C?= =?UTF-8?q?=E7=B4=A2=E3=82=AF=E3=82=A8=E3=83=AA=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `pegasus search` コマンドを追加し、特定の検索クエリに基づいたスクレイピングを可能にしました。 --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7a7930a..2705a2b 100644 --- a/README.md +++ b/README.md @@ -53,15 +53,22 @@ pip install pegasus-surf PEGASUSをコマンドラインから使用するには、以下のようなコマンドを実行します。 +#### 検索スクレイピング +```shell +pegasus search --search-query "お好み焼き レシピ" +``` + +#### 再帰スクレイピング + ```shell # 単一のURLからスクレイピングを開始 🌐 -pegasus --base-url https://example.com/start-page output_directory --exclude-selectors header footer nav --include-domain example.com --exclude-keywords login --output-extension .txt +pegasus recursive --base-url https://www.otafuku.co.jp/recipe/cook/noodle/nood01.html --output_dir output/yakisoba --exclude-selectors header footer nav --include-domain example.com --exclude-keywords login --output-extension .txt # 探索深度を指定して実行 🔍 -pegasus --base-url https://docs.eraser.io/docs/what-is-eraser output/eraser_docs2 --exclude-selectors header footer nav aside .sidebar .header .footer .navigation .breadcrumbs --include-domain docs.eraser.io --exclude-keywords login --output-extension .txt --max-depth 2 +pegasus recursive --base-url https://docs.eraser.io/docs/what-is-eraser --output_dir output/eraser_docs2 --exclude-selectors header footer nav aside .sidebar .header .footer .navigation .breadcrumbs --include-domain docs.eraser.io --exclude-keywords login --output-extension .txt --max-depth 2 # URLリストが記載されたテキストファイルからスクレイピングを開始 📜 -pegasus --url-file urls.txt output/roomba --exclude-selectors header footer nav aside .sidebar .header .footer .navigation .breadcrumbs --exclude-keywords login --output-extension .txt --max-depth 1 +pegasus recursive --url-file urls.txt --output_dir output/okonomi --exclude-selectors header footer nav aside .sidebar .header .footer .navigation .breadcrumbs --exclude-keywords login --output-extension .txt --max-depth 1 # LLMを使用したサイトの分類を行いながらスクレイピング 🧠 pegasus --url-file urls.txt output/roomba2 --exclude-selectors header footer nav aside .sidebar .header .footer .navigation .breadcrumbs --exclude-keywords login --output-extension .txt --max-depth 1 --system-message "あなたは、与えられたウェブサイトのコンテンツが特定のトピックに関連する有用な情報を含んでいるかどうかを判断するアシスタントです。トピックに関連する有益な情報が含まれている場合は「True」、そうでない場合は「False」と回答してください。" --classification-prompt "次のウェブサイトのコンテンツは、Roomba APIやiRobotに関する有益な情報を提供していますか? 提供している場合は「True」、そうでない場合は「False」と回答してください。" From 547783eb8b64b8531c2cf4572ab72d139777c293 Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 22:42:27 +0900 Subject: [PATCH 03/11] =?UTF-8?q?=F0=9F=94=8D=20(#2)[feat]=20DuckDuckGo?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E7=94=A8=E3=81=97=E3=81=9F=E3=83=AC=E3=82=B7?= =?UTF-8?q?=E3=83=94=E6=A4=9C=E7=B4=A2=E3=82=B9=E3=82=AF=E3=83=AA=E3=83=97?= =?UTF-8?q?=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新規スクリプトを作成し、お好み焼きレシピの検索と結果表示機能を実装しました。 --- example/ex06_ddg_recipe_query.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 example/ex06_ddg_recipe_query.py diff --git a/example/ex06_ddg_recipe_query.py b/example/ex06_ddg_recipe_query.py new file mode 100644 index 0000000..67f334e --- /dev/null +++ b/example/ex06_ddg_recipe_query.py @@ -0,0 +1,21 @@ +from duckduckgo_search import DDGS +import json + +# クエリ +with DDGS() as ddgs: + results = list(ddgs.text( + keywords='お好み焼き レシピ', # 検索ワード + region='jp-jp', # リージョン 日本は"jp-jp",指定なしの場合は"wt-wt" + safesearch='off', # セーフサーチOFF->"off",ON->"on",標準->"moderate" + timelimit=None, # 期間指定 指定なし->None,過去1日->"d",過去1週間->"w", + # 過去1か月->"m",過去1年->"y" + max_results=4 # 取得件数 + )) + +# レスポンスの表示 +for line in results: + print(json.dumps( + line, + indent=2, + ensure_ascii=False + )) \ No newline at end of file From f79784d8a20a69245ef196704c0b9c5d78efd952 Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 22:42:31 +0900 Subject: [PATCH 04/11] =?UTF-8?q?=F0=9F=94=84=20(#2)[feat]=20=E5=86=8D?= =?UTF-8?q?=E5=B8=B0=E3=82=B9=E3=82=AF=E3=83=AC=E3=82=A4=E3=83=94=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=81=A8=E6=A4=9C=E7=B4=A2=E3=82=B9=E3=82=AF=E3=83=AC?= =?UTF-8?q?=E3=82=A4=E3=83=94=E3=83=B3=E3=82=B0=E6=A9=9F=E8=83=BD=E3=82=92?= =?UTF-8?q?=E7=B5=B1=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 検索スクレイピングおよび再帰スクレイピングのメソッドを追加し、拡張性を高めました。 --- pegasus/Pegasus.py | 70 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/pegasus/Pegasus.py b/pegasus/Pegasus.py index 8d2a816..8f67f44 100644 --- a/pegasus/Pegasus.py +++ b/pegasus/Pegasus.py @@ -10,14 +10,15 @@ from litellm import completion from tqdm import tqdm import litellm -# litellm.set_verbose=True +from duckduckgo_search import DDGS +import json logger = loguru.logger class Pegasus: def __init__(self, output_dir, exclude_selectors=None, include_domain=None, exclude_keywords=None, output_extension=".md", dust_size=1000, max_depth=None, system_message=None, classification_prompt=None, max_retries=3, - model='gemini/gemini-1.5-pro-latest', rate_limit_sleep=60, other_error_sleep=10): + model='gemini/gemini-1.5-pro-latest', rate_limit_sleep=60, other_error_sleep=10, search_query=None, max_results=10, base_url=None, url_file="urls.txt"): self.output_dir = output_dir self.exclude_selectors = exclude_selectors self.include_domain = include_domain @@ -33,6 +34,10 @@ def __init__(self, output_dir, exclude_selectors=None, include_domain=None, excl self.model = model self.rate_limit_sleep = rate_limit_sleep self.other_error_sleep = other_error_sleep + self.search_query = search_query + self.max_results = max_results + self.base_url = base_url + self.url_file = url_file tprint(" Pegasus ", font="rnd-xlarge") logger.info("初期化パラメータ:") logger.info(f" output_dir: {output_dir}") @@ -48,6 +53,34 @@ def __init__(self, output_dir, exclude_selectors=None, include_domain=None, excl logger.info(f" model: {model}") logger.info(f" rate_limit_sleep: {rate_limit_sleep}") logger.info(f" other_error_sleep: {other_error_sleep}") + logger.info(f" search_query: {search_query}") + logger.info(f" max_results: {max_results}") + logger.info(f" base_url: {base_url}") + logger.info(f" url_file: {url_file}") + + + def search_scraping(self): + tprint(">> Search Scraping ") + if self.search_query is None: + return + + with DDGS() as ddgs: + results = list(ddgs.text( + keywords=self.search_query, + region='jp-jp', + safesearch='off', + timelimit=None, + max_results=self.max_results + )) + + with open("urls.txt", "w", encoding="utf-8") as file: + for result in results: + url = result['href'] + title = result['title'] + body = result['body'] + file.write(f"{url}, {title}, {body[:20]}\n") + + logger.info(f"検索スクレイピング完了 .... {self.max_results}件取得") def filter_site(self, markdown_content): if(self.classification_prompt is None): @@ -61,7 +94,7 @@ def filter_site(self, markdown_content): {"role": "user", "content": f"{self.classification_prompt}\n\n{markdown_content}"} ] response = completion( - model="gemini/gemini-1.5-pro-latest", + model=self.model, messages=messages ) content = response.get('choices', [{}])[0].get('message', {}).get('content') @@ -77,9 +110,9 @@ def filter_site(self, markdown_content): logger.warning(f"フィルタリングでエラーが発生しました。リトライします。({retry_count}/{self.max_retries})\nError: {e}") if "429" in str(e): - sleep_time = self.rate_limit_sleep # レート制限エラー時のスリープ時間をself.rate_limit_sleepから取得 + sleep_time = self.rate_limit_sleep else: - sleep_time = self.other_error_sleep # その他のエラー時のスリープ時間をself.other_error_sleepから取得 + sleep_time = self.other_error_sleep for _ in tqdm(range(sleep_time), desc="Sleeping", unit="s"): time.sleep(1) @@ -87,7 +120,7 @@ def filter_site(self, markdown_content): logger.error(f"フィルタリングに失敗しました。リトライ回数の上限に達しました。({self.max_retries}回)") return True - def download_and_convert(self, url, depth=0): + def download_and_convert(self, url, title, depth=0): if url in self.visited_urls: return self.visited_urls.add(url) @@ -130,7 +163,7 @@ def download_and_convert(self, url, depth=0): with open(output_file, 'w', encoding='utf-8') as file: file.write(markdown_content) - logger.info(f"[{depth}]変換成功: {url} ---> {output_file} [{len(markdown_content)/1000}kb]") + logger.info(f"[Depth:{depth}]変換成功: {url} ---> {output_file} [{len(markdown_content)/1000}kb]") if domain not in self.domain_summaries: self.domain_summaries[domain] = [] @@ -148,7 +181,7 @@ def download_and_convert(self, url, depth=0): if any(keyword in absolute_url for keyword in self.exclude_keywords): continue absolute_url = absolute_url.split('#')[0] - self.download_and_convert(absolute_url, depth + 1) + self.download_and_convert(absolute_url, title, depth + 1) except requests.exceptions.RequestException as e: logger.error(f"ダウンロードエラー: {url}: {e}") @@ -162,8 +195,21 @@ def create_domain_summaries(self): file.write('\n\n'.join(summaries)) logger.info(f"サマリーファイル作成: {summary_file}") - def run(self, base_url): - logger.info(f"スクレイピング開始: base_url={base_url}") - self.download_and_convert(base_url) + def recursive_scraping(self): + tprint(">> Recursive Scraping ") + logger.info("再帰スクレイピング開始") + if self.base_url: + logger.info(f"base_url={self.base_url} から再帰スクレイピングを開始します") + self.download_and_convert(self.base_url, "") + else: + with open("urls.txt", "r", encoding="utf-8") as file: + for line in file: + parts = line.strip().split(",") + url = parts[0] + title = parts[1] if len(parts) > 1 else "" + logger.info(f"---------------------------------------") + logger.info(f"スクレイピング開始: url={url}") + if(title): logger.info(f"タイトル: {title})") + self.download_and_convert(url, title) self.create_domain_summaries() - logger.info("スクレイピング完了") \ No newline at end of file + logger.info("再帰スクレイピング完了") \ No newline at end of file From 310d4fe729431b5bf57126ef0ad7dc38359e72e1 Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 22:42:34 +0900 Subject: [PATCH 05/11] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20(#2)[feat]=20CLI?= =?UTF-8?q?=E3=81=AE=E9=81=B8=E6=8A=9E=E8=82=A2=E3=82=92=E6=8B=A1=E5=A4=A7?= =?UTF-8?q?=E3=81=97=E3=80=81=E3=83=A2=E3=83=BC=E3=83=89=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E3=81=AB=E3=82=88=E3=82=8B=E5=8B=95=E4=BD=9C=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=E3=82=92=E3=82=B5=E3=83=9D=E3=83=BC=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `search` および `recursive` の二つのモードを実行可能にし、より柔軟なスクレイピング操作を提供します。 --- pegasus/cli.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/pegasus/cli.py b/pegasus/cli.py index 3967257..cf1e398 100644 --- a/pegasus/cli.py +++ b/pegasus/cli.py @@ -5,9 +5,8 @@ def main(): parser = argparse.ArgumentParser(description='Pegasus') - parser.add_argument('--base-url', help='スクレイピングを開始するベースURL') - parser.add_argument('--url-file', help='スクレイピングするURLが記載されたテキストファイル') - parser.add_argument('output_dir', help='Markdownファイルの出力ディレクトリ') + parser.add_argument('mode', choices=['search', 'recursive'], help='実行モード(検索スクレイピングまたは再帰スクレイピング)') + parser.add_argument('--output_dir', default='output', help='Markdownファイルの出力ディレクトリ') parser.add_argument('--exclude-selectors', nargs='+', help='除外するCSSセレクター') parser.add_argument('--include-domain', default='', help='URLマッチングに含めるドメイン') parser.add_argument('--exclude-keywords', nargs='+', help='URLマッチングから除外するキーワード') @@ -20,7 +19,11 @@ def main(): parser.add_argument('--model', default='gemini/gemini-1.5-pro-latest', help='LiteLLMのモデル名 (デフォルト: gemini/gemini-1.5-pro-latest)') parser.add_argument('--rate-limit-sleep', type=int, default=60, help='レート制限エラー時のスリープ時間(秒) (デフォルト: 60)') parser.add_argument('--other-error-sleep', type=int, default=10, help='その他のエラー時のスリープ時間(秒) (デフォルト: 10)') - + parser.add_argument('--search-query', help='検索スクレイピングで使用するクエリ') + parser.add_argument('--max-results', type=int, default=3, help='検索スクレイピングの最大数') + parser.add_argument('--base-url', help='再帰スクレイピングを開始するベースURL') + parser.add_argument('--url-file', default="urls.txt", help='スクレイピングするURLが記載されたテキストファイル') + args = parser.parse_args() pegasus = Pegasus( @@ -33,18 +36,20 @@ def main(): max_depth=args.max_depth, system_message=args.system_message, classification_prompt=args.classification_prompt, - max_retries=args.max_retries + max_retries=args.max_retries, + model=args.model, + rate_limit_sleep=args.rate_limit_sleep, + other_error_sleep=args.other_error_sleep, + search_query=args.search_query, + max_results=args.max_results, + base_url=args.base_url, + url_file=args.url_file ) - if args.base_url: - pegasus.run(args.base_url) - elif args.url_file: - with open(args.url_file, 'r') as file: - urls = file.read().splitlines() - for url in urls: - pegasus.run(url) - else: - parser.error("--base-url または --url-file のいずれかを指定してください。") + if args.mode == 'search': + pegasus.search_scraping() + elif args.mode == 'recursive': + pegasus.recursive_scraping() if __name__ == '__main__': main() \ No newline at end of file From e2ebc1d1d6178a0e2af6a8c9da64748da27ba897 Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 22:42:37 +0900 Subject: [PATCH 06/11] =?UTF-8?q?=F0=9F=93=A6=20(#2)[chore]=20=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E3=81=AA=E4=BE=9D=E5=AD=98=E9=96=A2=E4=BF=82=E3=81=AB?= =?UTF-8?q?=20DuckDuckGo=20search=20=E3=83=A9=E3=82=A4=E3=83=96=E3=83=A9?= =?UTF-8?q?=E3=83=AA=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DuckDuckGo search ライブラリをdependenciesに追加し、新機能のサポートを強化しました。 --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 965ba23..14210c2 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,7 @@ 'litellm', 'python-dotenv', 'google-generativeai', + 'duckduckgo-search', ], entry_points={ 'console_scripts': [ From 233951bdc9719a4e44ec4c491034c6139c81e62c Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 23:05:10 +0900 Subject: [PATCH 07/11] =?UTF-8?q?=F0=9F=93=9D=20(#1)[docs]=20=E3=82=B9?= =?UTF-8?q?=E3=82=AF=E3=83=AC=E3=82=A4=E3=83=94=E3=83=B3=E3=82=B0=E3=82=AA?= =?UTF-8?q?=E3=83=97=E3=82=B7=E3=83=A7=E3=83=B3=E3=81=AE=E8=AA=AC=E6=98=8E?= =?UTF-8?q?=E3=82=92=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - メソッドの変更に伴い、READMEファイル内のコマンド例を更新し、正確な使用方法を反映しました。 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2705a2b..2217f4b 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ pegasus recursive --base-url https://docs.eraser.io/docs/what-is-eraser --outp pegasus recursive --url-file urls.txt --output_dir output/okonomi --exclude-selectors header footer nav aside .sidebar .header .footer .navigation .breadcrumbs --exclude-keywords login --output-extension .txt --max-depth 1 # LLMを使用したサイトの分類を行いながらスクレイピング 🧠 -pegasus --url-file urls.txt output/roomba2 --exclude-selectors header footer nav aside .sidebar .header .footer .navigation .breadcrumbs --exclude-keywords login --output-extension .txt --max-depth 1 --system-message "あなたは、与えられたウェブサイトのコンテンツが特定のトピックに関連する有用な情報を含んでいるかどうかを判断するアシスタントです。トピックに関連する有益な情報が含まれている場合は「True」、そうでない場合は「False」と回答してください。" --classification-prompt "次のウェブサイトのコンテンツは、Roomba APIやiRobotに関する有益な情報を提供していますか? 提供している場合は「True」、そうでない場合は「False」と回答してください。" +pegasus recursive --url-file urls.txt --output_dir output/roomba2 --exclude-selectors header footer nav aside .sidebar .header .footer .navigation .breadcrumbs --exclude-keywords login --output-extension .txt --max-depth 1 --system-message "あなたは、与えられたウェブサイトのコンテンツが特定のトピックに関連する有用な情報を含んでいるかどうかを判断するアシスタントです。トピックに関連する有益な情報が含まれている場合は「True」、そうでない場合は「False」と回答してください。" --classification-prompt "次のウェブサイトのコンテンツは、Roomba APIやiRobotに関する有益な情報を提供していますか? 提供している場合は「True」、そうでない場合は「False」と回答してください。" ``` オプションの意味はこんな感じです!👀 From cd2592cfc72b4154e55f14d22e2e73be54be279b Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 23:05:13 +0900 Subject: [PATCH 08/11] =?UTF-8?q?=F0=9F=90=9B=20(#1)[fix]=20=E6=96=87?= =?UTF-8?q?=E5=AD=97=E5=8C=96=E3=81=91=E6=A4=9C=E5=87=BA=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97=E3=81=A6=E3=82=B9=E3=82=AF?= =?UTF-8?q?=E3=83=AC=E3=82=A4=E3=83=94=E3=83=B3=E3=82=B0=E3=81=AE=E5=A0=85?= =?UTF-8?q?=E7=89=A2=E6=80=A7=E3=82=92=E5=90=91=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 文字化けを自動検出し、不正なテキストが含まれるページを除外する新機能を実装。 - ASCII範囲外の文字が多い場合、内容が文字化けしているとみなし、処理から除外します。 --- pegasus/Pegasus.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pegasus/Pegasus.py b/pegasus/Pegasus.py index 8f67f44..72d9488 100644 --- a/pegasus/Pegasus.py +++ b/pegasus/Pegasus.py @@ -139,6 +139,11 @@ def download_and_convert(self, url, title, depth=0): markdown_content = markdownify.markdownify(str(soup)) markdown_content = re.sub(r'\n{5,}', '\n\n\n\n', markdown_content) + # 文字化けチェック + if not self.is_valid_text(markdown_content): + logger.warning(f"文字化けを検出したため除外: {url}") + return + if not self.filter_site(markdown_content): parsed_url = urlparse(url) domain = parsed_url.netloc @@ -188,6 +193,17 @@ def download_and_convert(self, url, title, depth=0): except IOError as e: logger.error(f"書き込みエラー: {output_file}: {e}") + def is_valid_text(self, text): + # ASCII範囲外の文字の割合を計算 + non_ascii_chars = re.findall(r'[^\x00-\x7F]', text) + non_ascii_ratio = len(non_ascii_chars) / len(text) + + # 割合が一定以上であれば文字化けとみなす + if non_ascii_ratio > 0.3: + return False + else: + return True + def create_domain_summaries(self): for domain, summaries in self.domain_summaries.items(): summary_file = os.path.join(self.output_dir, f"{domain}_summary{self.output_extension}") From 1581e5de8e4d57d944e846083c14f42f576d4982 Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 23:11:59 +0900 Subject: [PATCH 09/11] =?UTF-8?q?=F0=9F=93=84=20(#4)[docs]=20README?= =?UTF-8?q?=E3=81=ABSourceSage=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1?= =?UTF-8?q?=E3=83=B3=E3=83=88=E8=87=AA=E5=8B=95=E7=94=9F=E6=88=90=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SourceSageを用いたドキュメント自動生成のコマンド例を追記し、具体的な使用方法を示しました。 - ドキュメント生成に必要なパラメータを明記し、ユーザーが容易に機能を利用できるようにしました。 --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 2217f4b..38de86f 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,11 @@ pegasus.run("https://example.com/start-page") [View on Eraser![](https://app.eraser.io/workspace/8cnaevNcF1kxMsfSfGl0/preview?elements=KStkmTRUuZ5AiJNPC8E40g&type=embed)](https://app.eraser.io/workspace/8cnaevNcF1kxMsfSfGl0?elements=KStkmTRUuZ5AiJNPC8E40g) +### SourceSage + +```shell +sourcesage --mode DocuMind --docuMind-model "gemini/gemini-1.5-pro-latest" --docuMind-db ".SourceSageAssets\DOCUMIND\Repository_summary.md" --docuMind-release-report ".SourceSageAssets\RELEASE_REPORT\Report_v0.3.0.md" --docuMind-changelog ".SourceSageAssets\Changelog\CHANGELOG_release_5.0.0.md" --docuMind-output ".SourceSageAssets/DOCUMIND/RELEASE_NOTES_v0.3.0.md" --docuMind-prompt-output ".SourceSageAssets/DOCUMIND/_PROMPT_v0.3.0.md" --repo-name "SourceSage" --repo-version "v0.5.0" +``` ## 🤝 貢献 From d2208a537e70b8c8a756e11e3cd60f15bca0afc8 Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 23:12:02 +0900 Subject: [PATCH 10/11] =?UTF-8?q?=F0=9F=94=A7=20(#4)[chore]=20.gitignore?= =?UTF-8?q?=E3=81=ABmemo.md=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ローカル開発中に生成されるmemo.mdファイルをGitの追跡対象から除外しました。 - これにより、開発者がローカルでメモを取りながら作業できるようになり、Gitリポジトリの清潔さを保持します。 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a9edce7..0c8f280 100644 --- a/.gitignore +++ b/.gitignore @@ -169,3 +169,4 @@ tmp2.md .harmon_ai/README_template.md output urls.txt +memo.md From 72d07d24dfa1a864162c6c2b98a4df24c1a555de Mon Sep 17 00:00:00 2001 From: Maki Date: Mon, 10 Jun 2024 23:16:16 +0900 Subject: [PATCH 11/11] =?UTF-8?q?=F0=9F=93=9D=20(#4)[docs]=20SourceSage?= =?UTF-8?q?=E3=81=AE=E3=83=AA=E3=83=9D=E3=82=B8=E3=83=88=E3=83=AA=E3=83=90?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E7=95=AA=E5=8F=B7=E3=82=92?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SourceSageのドキュメント生成コマンドのバージョン番号を`v0.5.0`から`v0.3.0`に修正しました。 - これにより、適切なバージョンのドキュメントリソースを参照するように変更して、整合性を保持します。 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 38de86f..ace1b28 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ pegasus.run("https://example.com/start-page") ### SourceSage ```shell -sourcesage --mode DocuMind --docuMind-model "gemini/gemini-1.5-pro-latest" --docuMind-db ".SourceSageAssets\DOCUMIND\Repository_summary.md" --docuMind-release-report ".SourceSageAssets\RELEASE_REPORT\Report_v0.3.0.md" --docuMind-changelog ".SourceSageAssets\Changelog\CHANGELOG_release_5.0.0.md" --docuMind-output ".SourceSageAssets/DOCUMIND/RELEASE_NOTES_v0.3.0.md" --docuMind-prompt-output ".SourceSageAssets/DOCUMIND/_PROMPT_v0.3.0.md" --repo-name "SourceSage" --repo-version "v0.5.0" +sourcesage --mode DocuMind --docuMind-model "gemini/gemini-1.5-pro-latest" --docuMind-db ".SourceSageAssets\DOCUMIND\Repository_summary.md" --docuMind-release-report ".SourceSageAssets\RELEASE_REPORT\Report_v0.3.0.md" --docuMind-changelog ".SourceSageAssets\Changelog\CHANGELOG_release_5.0.0.md" --docuMind-output ".SourceSageAssets/DOCUMIND/RELEASE_NOTES_v0.3.0.md" --docuMind-prompt-output ".SourceSageAssets/DOCUMIND/_PROMPT_v0.3.0.md" --repo-name "SourceSage" --repo-version "v0.3.0" ``` ## 🤝 貢献