ç§ã¯ãnoteã®ããã°ã«é¢ããŠãå 容ãèŠçŽããããåŸåãåæããããé¢é£ãã質åã«çãããã§ããAIããããäœæããŸãããã©ã®ããã«ããŠå®çŸããã®ã§ããããïŒ
ã¿ãªãããããã«ã¡ã¯ïŒAIã«é¢ããé¢çœããããã¯ãæ¢ãããã«ã1ã2æéã»ã©noteãçºããŠããããããããããããå€ãããã°ã®æ
å ±ãæœåºããŠãèŠçŽããŠãããAIããããäœã£ããé¢çœããªãïŒãã£ãŠæã£ããã§ãããããããããã«åãããã£ã¡ãããŸãã=))))ã
ãã®ããã°ã§ã¯ããã®AIããããäžããäœãæ¹æ³ãã¹ãããããšã«è§£èª¬ããŠãããŸãïŒ
以äžã¯ãç§ã®ããããïŒçŽè¿20ä»¶ã®ããã°ããã§ãã¯ããåŸã«ïŒè¿çããããã€ãã®çµæã§ãã



ãããå§ãããïŒ
AIãããã¯ã©ã®ããã«åäœããã®ãïŒ
æ¬è³ªçã«ã¯ããã®AIãããã¯ãŠã§ãã¹ã¯ã¬ã€ãã³ã°ãèªç¶èšèªåŠçïŒNLPïŒããããŠOpenAIã®GPTã®ãããªåŒ·åãªèšèªã¢ãã«ãçµã¿åãããããšã§ãããã°ã®å 容ãçè§£ãã察話ããããšãã§ããŸãã
ã¹ããã1ïŒãŠã§ãã¹ã¯ã¬ã€ãã³ã°ã«ããããŒã¿åé
ã¹ããã2ïŒããŒã¿ã®æŽåãšæ§é å
ã¹ããã3ïŒèšèªã¢ãã«ã«ãã質åå¿ç
ãŠã§ãã¹ã¯ã¬ã€ãã³ã°ã«ããããŒã¿åé
ãŸãããããã¯ãŠã§ãã¹ã¯ã¬ã€ãã³ã°æè¡ã䜿ã£ãŠããã°ã®ããŒã¿ãåéããŸããå
·äœçã«ã¯ãããã°ã©ã ã§ããã°ããŒãžã«ã¢ã¯ã»ã¹ããã¿ã€ãã«ãèè
ãå
¬éæ¥ãæ¬æãªã©ã®å¿
èŠãªæ
å ±ãæœåºããŸãã
SeleniumãšBeautifulSoupã䜿ãã°ãåçãªããŒãžã®èªã¿èŸŒã¿ãšãå¿
èŠãªããã¹ãã®è§£æãå¯èœã§ãã
ãã®åŠçãè¡ãããã«ãdata_scrapper.pyãšãããã¡ã€ã«ãäœæããŠãnoteããã®ããŒã¿åéãæ
åœãããŸãã
ãŸãåãã«ããŠã§ããã©ãŠã¶ãèªåæäœããHTMLã³ã³ãã³ããè§£æããããã«å¿ èŠãªPythonã©ã€ãã©ãªãã€ã³ããŒãããŸãã
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import timeChromeããããã¬ã¹ã¢ãŒãã§å®è¡ããããã«èšå®ããŸãããããã¬ã¹ã¢ãŒãã§ã¯ããã©ãŠã¶ã®ç»é¢ïŒGUIïŒã衚瀺ããã«æäœã§ããããããµãŒããŒç°å¢ãCIãã€ãã©ã€ã³ã§èªååã¹ã¯ãªãããå®è¡ããéã«äŸ¿å©ã§ãã
# Chromeããããã¬ã¹ã¢ãŒãã§èµ·åããããã®èšå®
options = Options()
options.add_argument('--headless') # ãããã¬ã¹ã¢ãŒããæå¹åïŒç»é¢ãªãã§ãã©ãŠã¶ãæäœïŒ
options.add_argument('--disable-gpu') # GPUãç¡å¹åïŒãããã¬ã¹ã§ã®å®å®åäœã®ããïŒ
options.add_argument('--no-sandbox') # ãµã³ãããã¯ã¹æ©èœãç¡å¹åïŒLinuxç°å¢ã§å¿
èŠãªå ŽåããïŒ
options.add_argument('--disable-software-rasterizer') # ãœãããŠã§ã¢ã©ã¹ã¿ã©ã€ã¶ãŒãç¡å¹å
options.add_argument('--disable-dev-shm-usage') # /dev/shmã®äœ¿çšãç¡å¹åïŒã¡ã¢ãªäžè¶³åé¿çšïŒ
options.add_argument('--disable-3d-apis') # 3D APIãç¡å¹å
options.add_argument('--disable-webgl') # WebGLãç¡å¹å
options.add_argument('--disable-features=VizDisplayCompositor') # VizDisplayCompositoræ©èœãç¡å¹åèšå®ãããªãã·ã§ã³ã䜿ã£ãŠãChromeãã©ãŠã¶ãèµ·åããŸãã
driver = webdriver.Chrome(options=options)ããã«ãããSeleniumã«ãã£ãŠå¶åŸ¡ããããããã¬ã¹ã¢ãŒãã®Chromeãã©ãŠã¶ãèµ·åããŸãã
次ã«ãåºæºãšãªãURLãšãã¹ã¯ã¬ã€ãã³ã°ãããç¹å®ã®ããŒãžãå®çŸ©ããŸãã
root = r"https://note.com"
link = r"https://note.com/interests"åããã°èšäºã®è©³çްãªå 容ãååŸããããã«ãããã°ã®URLãžç§»åããããŒãžãœãŒã¹ãååŸããŠæ¬æã®äž»èŠéšåãè§£æãã颿°ãå®çŸ©ããŸãããã®é¢æ°ã¯ãå®å šãªURLãšçžå¯Ÿãªã³ã¯ã®äž¡æ¹ã«å¯Ÿå¿ããŠãããé¢é£ããæ®µèœãèŠåºããæœåºããŠãããã°ã®èªã¿ãããããã¹ãèŠçŽãäœæããŸãã
# ããã°ã®è©³çްã³ã³ãã³ããååŸãã颿°
def get_detail_content_from_blog(ããã°ã®ãªã³ã¯):
# ãã«URLã§ãªããã°ãã«ãŒãURLãä»ããŠã¢ã¯ã»ã¹
if "https://note" not in ããã°ã®ãªã³ã¯:
driver.get(æ ¹ + ããã°ã®ãªã³ã¯)
else:
driver.get(ããã°ã®ãªã³ã¯)
html = driver.page_source
ã¹ã¯ã¬ã€ãã³ã° = BeautifulSoup(html, "html.parser")
# æ¬æãå«ãŸããdivèŠçŽ ïŒã¯ã©ã¹ånote-common-styles__textnote-bodyïŒãååŸ
ã»ã¯ã·ã§ã³ã»ãã = ã¹ã¯ã¬ã€ãã³ã°.select_one(".note-common-styles__textnote-body")
if ã»ã¯ã·ã§ã³ã»ãã:
# æ¬æäžã®<p>, <h2>ïœ<h6>ã¿ã°ããã¹ãŠååŸ
ã»ã¯ã·ã§ã³ = ã»ã¯ã·ã§ã³ã»ãã.find_all(['p', 'h2', 'h3', 'h4', 'h5', 'h6'])
# åã¿ã°ã®ããã¹ããæ¹è¡ã§ç¹ããŠ1ã€ã®æååã«ãŸãšãã
ããã¹ã = "\n".join([tag.get_text(strip=True) for tag in ã»ã¯ã·ã§ã³])
return ããã¹ã
else:
# æ¬æãèŠã€ãããªãã£ãå Žåã¯ç©ºæåãè¿ã
return ""æå®ããã«ããŽãªãŒã®ããã°ããŒã¿ãç¹å®ã®ãŠã§ããµã€ãããã¹ã¯ã¬ã€ãã³ã°ãã颿°ã§ããSeleniumãã©ã€ããŒã䜿çšããŠããŒãžã«ã¢ã¯ã»ã¹ããæå€§20ä»¶ã®ããã°ãšã³ããªãæœåºããŸãã åããã°ãããå ¬éæéããããæ°ãèè ããªã³ã¯ãã¿ã€ãã«ãã³ã³ãã³ããšãã£ãæ å ±ãååŸããŸãã ããã°èšäºã®è©³çްã³ã³ãã³ãã¯ãè£å©é¢æ° `get_detail_content_from_blog()` ã䜿ã£ãŠååŸãããŸããæå®ãããã«ããŽãªãŒãååšããªãå Žåããã¹ã¯ã¬ã€ãã³ã°ã«å€±æããå Žåã¯ãNone ãè¿ããŸãã
# æå®ããåéã®ããã°ããŒã¿ãã¹ã¯ã¬ã€ãã³ã°ãã颿°
def DataScrapper(åé):
driver.get(ãªã³ã¯ + "/" + åé)
time.sleep(3) # ããŒãžèªã¿èŸŒã¿ã®ãã3ç§åŸ
æ©
html = driver.page_source
try:
ã¹ã¯ã¬ã€ãã³ã° = BeautifulSoup(html, "html.parser")
# ç¹å®ã®divèŠçŽ ïŒã¯ã©ã¹hidden sm:grid gap-4ïŒãååŸ
ã»ã¯ã·ã§ã³ã»ãã = ã¹ã¯ã¬ã€ãã³ã°.select_one("div.hidden.sm\\:grid.gap-4")
# ãã®äžã®æåã®20åã®<section>ã¿ã°ãæœåº
ã»ã¯ã·ã§ã³ = ã»ã¯ã·ã§ã³ã»ãã.find_all('section')[:20] if ã»ã¯ã·ã§ã³ã»ãã else []
ããã°ã»ãã = []
for i, sec in enumerate(ã»ã¯ã·ã§ã³):
# print(f"Record {i}")
ããã° = {
"å
¬éæé": "",
"ããã": "",
"èè
": "",
"ãªã³ã¯": "",
"ã¿ã€ãã«": "",
"ã³ã³ãã³ã": ""
}
# å
¬éæéãååŸ
ããã°["å
¬éæé"] = sec.find('time').get_text(strip=True)
# ãããæ°ãååŸ
ããã°["ããã"] = sec.find('span', class_='pl-2 text-sm text-text-secondary').get_text(strip=True)
# èè
åãååŸ
ããã°["èè
"] = sec.find('span', class_='o-noteItem__userText').get_text(strip=True)
# èšäºãžã®ãªã³ã¯ãååŸ
ããã°["ãªã³ã¯"] = sec.find('a')['href']
# èšäºã¿ã€ãã«ãååŸ
ããã°["ã¿ã€ãã«"] = sec.find('h3', class_='m-noteBodyTitle__title').get_text(strip=True)
# èšäºã®è©³çްã³ã³ãã³ããååŸãã颿°ãåŒã³åºã
ããã°["ã³ã³ãã³ã"] = get_detail_content_from_blog(ããã°["ãªã³ã¯"])
ããã°ã»ãã.append(ããã°)
print("ããŒã¿ãã¹ã¯ã¬ã€ãã³ã°ããŸããã")
return ããã°ã»ãã
except:
print("ãã®åéã¯èŠã€ãããŸããã")
return NoneããŒã¿ã®æŽåãšæ§é å
main.py ãäœæããŠããŠãŒã¶ãŒãåéïŒèå³ã®ããã«ããŽãªïŒãšã¯ãšãªïŒè³ªåïŒãå ¥åã§ããããã«ããŸããæåã«ãDataScrapper 颿°ã䜿ã£ãŠãæå®ãããåéã«é¢é£ããããã°ããŒã¿ãã¹ã¯ã¬ã€ãã³ã°ããŸãããã®åŸãç¡éã«ãŒãã«å ¥ãããŠãŒã¶ãŒã®ã¯ãšãªãç¹°ãè¿ãåãåããLLM_Response 颿°ã«ã¯ãšãªãšããã°ããŒã¿ãæž¡ããŠåçãçæããŸããçæãããçãã¯ã³ã³ãœãŒã«ã«è¡šç€ºããããŠãŒã¶ãŒã¯æ°ãã質åãç¶ããŠå ¥åããããšãã§ããŸãããŸãããããã°ç®çã§ãããã°ããŒã¿å šäœãæŽåœ¢ããã JSON 圢åŒã§åºåã§ããã³ã¡ã³ãã¢ãŠããããè¡ãçšæãããŠããŸãã
from data_scrapper import DataScrapper
from llm_response import LLM_Response
import json
# ãŠãŒã¶ãŒã«åéåãå
¥åããŠããã
åé = input("åéãå
¥åããŠãã ãã: ")
# ãŠãŒã¶ãŒã«è³ªåãå
¥åããŠããã
ããã = input("ããããå
¥åããŠãã ãã: ")
# æå®ãããåéã®ããã°ããŒã¿ãã¹ã¯ã¬ã€ãã³ã°ããŠååŸ
ããã°ã»ãã = DataScrapper(åé)
# ç¡éã«ãŒãã§è³ªåã«å¯Ÿããåçãç¹°ãè¿ã衚瀺
while True:
# LLMã«è³ªåãšããã°ããŒã¿ãæž¡ããŠåçãååŸ
respone = LLM_Response(ããã, ããã°ã»ãã)
# åçã衚瀺
print("--------------------------------------------")
print("çã:")
print(respone)
print("--------------------------------------------")
# 次ã®è³ªåããŠãŒã¶ãŒããå
¥åããŠããã
ããã = input("ããããå
¥åããŠãã ãã: ")
# ããã°ããŒã¿ã»ãããJSON圢åŒã§æŽåœ¢ããŠè¡šç€ºïŒãããã°çšïŒ
# print(json.dumps(ããã°ã»ãã, ensure_ascii=False, indent=2))èšèªã¢ãã«ã«ãã質åå¿ç
ãã®é¢æ°ã¯ãæå®ãããããã³ããã䜿ã£ãŠ OpenAI ã® API ãåŒã³åºããå¿çãçæããããã®é¢æ°ã§ããOpenAI ã¯ã©ã€ã¢ã³ãã® chat.completions.create ã¡ãœããã䜿çšããŠããŸããããã³ããã¯2ã€ã®ã¡ãã»ãŒãžã§æ§æãããŠããã1ã€ç®ã¯ã¢ã·ã¹ã¿ã³ãã®åœ¹å²ãå®çŸ©ãããã·ã¹ãã ã¡ãã»ãŒãžãïŒãã®å Žåã¯å€§éã®ããŒã¿ã»ããã«é¢ãã質åã«çããããè³¢ãã¢ã·ã¹ã¿ã³ãïŒã2ã€ç®ã¯ãŠãŒã¶ãŒããã®å®éã®è³ªåãå«ãããŠãŒã¶ãŒã¡ãã»ãŒãžãã§ãã
䜿çšãããã¢ãã«ã¯ gpt-4o-mini ã§ãå¿çã¯äžçšåºŠã®åµé æ§ïŒtemperature=0.7ïŒããã£ãŠçæãããŸããAPI åŒã³åºããæåããã°ãã¢ã·ã¹ã¿ã³ãã®å¿çããã¬ãŒã³ããã¹ãã§è¿ãããŸããäžæ¹ãAPI åŒã³åºãæã«ãšã©ãŒãçºçããå Žåã¯ããšã©ãŒã¡ãã»ãŒãžãè¿ãããŸãã
from openai import OpenAI
client = OpenAI(api_key='YOUR_API_KEY')
# OpenAIã®APIãåŒã³åºããŠå¿çãçæãã颿°
def generate_openai_response(ã·ã¹ãã ããã³ãã, model="gpt-4o-mini", max_tokens=1500):
try:
response = client.chat.completions.create(
model=model,
messages=[
# ã·ã¹ãã ã¡ãã»ãŒãžïŒAIã®åœ¹å²ãæå®ïŒ
{"role": "system", "content": "ããªãã¯ã倧éã®ããŒã¿ã»ããã«é¢ãã質åã«çããããšãã§ããè³¢ãã¢ã·ã¹ã¿ã³ãã§ãã"},
# ãŠãŒã¶ãŒã¡ãã»ãŒãžïŒè³ªåå
容ïŒ
{"role": "user", "content": ã·ã¹ãã ããã³ãã}
],
#max_tokens=max_tokens, # æå€§ããŒã¯ã³æ°ïŒå¿
èŠã«å¿ããŠäœ¿çšïŒ
temperature=0.7, # åµé æ§ã®åºŠåãïŒ0.7ã¯ããã©ã³ãã ãªå¿çïŒ
)
# å¿çããã¹ããè¿ã
return response.choices[0].message.content.strip()
except Exception as e:
# APIåŒã³åºãã§ãšã©ãŒãçºçããå Žåã®åŠç
return f"Lá»i khi gá»i API OpenAI: {e}"ãã®é¢æ°ã¯ãã·ã¹ãã ããã³ããïŒã¢ã·ã¹ã¿ã³ãã®åœ¹å²ãã§ããããšã®èª¬æïŒãšãŠãŒã¶ãŒã®è³ªåïŒãããïŒããããŠæäŸãããããã°ããŒã¿ïŒããã°ã»ããïŒãçµã¿åãããŠãå®å šãªããã³ãããæ§ç¯ããŸããããã³ããã®äžã§ã¯ã以äžã®ãããªã¢ã·ã¹ã¿ã³ãã®èœåãå®çŸ©ãããŠããŸãïŒ
ããããããæãå€ãããã°ãç¹å®ãã
ç¹å®ã®ããã°èšäºã®å 容ãèŠçŽãã
è€æ°ã®ããã°ã®åŸåãæ¯èŒã«é¢ãã質åã«çãã
ãã¬ãŒã³ããã¹ã圢åŒã®ããã°ããŒã¿ãæ£ç¢ºã«è§£éãã
ãŸãããã®ããã³ããã§ã¯ãæäŸãããããã°ããŒã¿ã®æ å ±ã®ã¿ã«åºã¥ããŠåçããããã«ããšæç€ºçã«æç€ºãããŠããŸããæ§ç¯ãããããã³ãã㯠generate_openai_response() 颿°ã«æž¡ãããã¢ãã«ããã®é©åãªåçãååŸãããŠè¿ãããŸãã
# ããã°ããŒã¿ã»ãããšãŠãŒã¶ãŒã®è³ªåãããOpenAIã«è³ªåãæããŠåçãåŸã颿°
def LLM_Response(ããã, ããã°ã»ãã):
ã·ã¹ãã ããã³ãã = (
f"""
ããªãã¯ãããã°ã®ãªã¹ããåæããããã«é¢ãã質åã«çããããšãã§ããæèœãªã¢ã·ã¹ã¿ã³ãã§ããåããã°ã«ã¯ãã¿ã€ãã«ãå
容ãèè
ããããæ°ãå
¬éæ¥æããªã³ã¯ãªã©ã®æ
å ±ãå«ãŸããŠããŸãã
ããªããã§ããããšïŒ
- æãå€ãã®ããããããã€ããŠããããã°ãç¹å®ããããš
- ç¹å®ã®ããã°ã®å
容ãèŠçŽããããš
- ããã°ã®äžã«èŠãããåŸåãæ¯èŒã詳现ã«ã€ããŠã®è³ªåã«çããããš
- ãã¬ãŒã³ããã¹ã圢åŒã§æäŸãããããã°ããŒã¿ãæ£ããè§£éããããš
äŒè©±ã®äžã§æäŸãããããã°ããŒã¿ã®æ
å ±ã®ã¿ã«åºã¥ããŠåçããŠãã ããã
**ããã°ããŒã¿ã»ãã**:
{ããã°ã»ãã}
**ãŠãŒã¶ãŒããã®è³ªå**:
{ããã}
"""
)
# OpenAI APIåŒã³åºã颿°ã«ããã³ãããæž¡ããŠå¿çãååŸ
return generate_openai_response(ã·ã¹ãã ããã³ãã)ãã£ããïŒãã£ããããã宿ããã§ãšãïŒð
ãã¡ãã®ã³ãŒããåèã«ããŠãã ããïŒhttps://github.com/MinhHung7/Note_blog_retrieval_chatbotAI
