commit 9a1a45d5049015ea6dc6fca5b5fc5ef4b3adbb89 Author: kyeongmin Date: Wed Feb 25 09:44:22 2026 +0900 Initial commit for ad-hoc items diff --git a/n8n/n8n 활용 문서(도커 설치 방법) .hwp b/n8n/n8n 활용 문서(도커 설치 방법) .hwp new file mode 100644 index 0000000..025941d Binary files /dev/null and b/n8n/n8n 활용 문서(도커 설치 방법) .hwp differ diff --git a/n8n/n8n을 활용한 뉴스 기사 수집 Sample .json b/n8n/n8n을 활용한 뉴스 기사 수집 Sample .json new file mode 100644 index 0000000..f2389a7 --- /dev/null +++ b/n8n/n8n을 활용한 뉴스 기사 수집 Sample .json @@ -0,0 +1,631 @@ +{ + "name": "test용", + "nodes": [ + { + "parameters": { + "messages": { + "message": [ + { + "content": "={{ $json.submittedAt }}를 기준으로, {{ $json['수집 기간'] }}동안에 {{ $json['키워드'] }}와 관련된 기사를 모두 수집 정리해줘. 공신력 있는 매체를 중심으로 수집하되, 유튜브, 동영상 링크는 제외해줘.\n\n아래 JSON 형식으로만 답변해줘.\n[\n {\n \"제목\": \"\",\n \"발행일\": \"\",\n \"매체\": \"\",\n \"URL\": \"\",\n }\n]" + } + ] + }, + "options": {}, + "requestOptions": {} + }, + "type": "n8n-nodes-base.perplexity", + "typeVersion": 1, + "position": [ + 176, + -224 + ], + "id": "d0e538a2-eeb9-4caf-a794-f1a6a0253a78", + "name": "Message a model", + "credentials": { + "perplexityApi": { + "id": "sJrK346BATWXY2dP", + "name": "Perplexity account" + } + } + }, + { + "parameters": { + "url": "={{ $json.search_results.url }}", + "options": {} + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [ + 608, + -224 + ], + "id": "a49db960-6302-4071-840e-c6496ac021c2", + "name": "HTTP Request" + }, + { + "parameters": { + "fieldToSplitOut": "search_results", + "include": "allOtherFields", + "options": {} + }, + "type": "n8n-nodes-base.splitOut", + "typeVersion": 1, + "position": [ + 384, + -224 + ], + "id": "ff741487-10c4-49e8-b1f8-79892ae029fa", + "name": "Split Out" + }, + { + "parameters": { + "url": "=https://news.google.com/rss/search?q={{ encodeURIComponent($json['키워드']) }}&hl=ko&gl=KR&ceid=KR:ko\n", + "options": {} + }, + "type": "n8n-nodes-base.rssFeedRead", + "typeVersion": 1.2, + "position": [ + 176, + 112 + ], + "id": "59eb818c-026e-4c89-98e9-ae3222c95a15", + "name": "RSS Read" + }, + { + "parameters": { + "url": "={{ $json.link }}", + "options": {} + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [ + 384, + 112 + ], + "id": "6df6e206-d0d6-4a69-8b0f-d8e7af9e9b44", + "name": "HTTP Request1" + }, + { + "parameters": { + "language": "pythonNative", + "pythonCode": "import time\nimport requests\nfrom bs4 import BeautifulSoup\nimport pandas as pd\nimport re\nimport logging\nimport os\nimport random\nimport ssl\nfrom datetime import datetime\nfrom requests.adapters import HTTPAdapter\nfrom urllib3.poolmanager import PoolManager\n\n# -------------------------------------------------\n# 설정: 로그 파일 및 기본 환경\n# -------------------------------------------------\nlog_file = os.path.join(os.path.dirname(__file__), '엔지니어링_일일_동향.log')\nlogging.basicConfig(\n filename=log_file,\n level=logging.DEBUG,\n format='%(asctime)s - %(levelname)s - %(message)s'\n)\nlogging.info('Script started')\n\n# -------------------------------------------------\n# 공통 전처리 함수\n# -------------------------------------------------\n\ndef clean_text(text: str) -> str:\n \"\"\"HTML 엔티티 및 불필요한 태그 제거\"\"\"\n reps = {\n ' ': ' ', '‘': \"'\", '’': \"'\", '“': '\"', '”': '\"',\n '&': '&', '<': '<', '>': '>', ''': \"'\", '"': \"'\", '·': \"'\"\n }\n for key, val in reps.items():\n text = text.replace(key, val)\n return re.sub(r'<[^>]+>', '', text).strip()\n\n\ndef fetch_article_content(url: str, source: str) -> str:\n \"\"\"단일 기사 본문 추출\"\"\"\n try:\n resp = requests.get(url, verify=False, timeout=10)\n resp.encoding = 'utf-8'\n resp.raise_for_status()\n soup = BeautifulSoup(resp.text, 'html.parser')\n paragraphs = soup.find_all('p')\n content = ' '.join(clean_text(p.get_text()) for p in paragraphs)\n content = content.replace('\\n', ' ')\n if not content.strip():\n logging.warning(f'No content for {url}')\n return f\"No content available #출처: {source}\"\n return content\n except Exception as e:\n logging.error(f'Error fetching content {url}: {e}')\n return f\"No content available #출처: {source}\"\n\n\ndef format_date(date_str: str, source: str) -> str:\n \"\"\"날짜 형식을 YYYY-MM-DD 로 변환\"\"\"\n try:\n match = re.search(r'\\d{4}-\\d{2}-\\d{2}', date_str)\n if match:\n return match.group(0)\n if source == '연합뉴스':\n return datetime.strptime(date_str, '%m-%d %H:%M').strftime('2024-%m-%d')\n return date_str\n except Exception:\n return date_str\n\n\ndef fetch_articles(\n base_url: str,\n article_sel: str,\n title_sel: str,\n date_sel: str,\n start_page: int,\n end_page: int,\n source: str,\n url_prefix: str = '',\n date_fmt_func=None\n) -> list:\n \"\"\"리스트 페이지 순회하며 메타데이터 및 본문 수집\"\"\"\n results = []\n for page in range(start_page, end_page + 1):\n try:\n page_url = f\"{base_url}{page}\"\n resp = requests.get(page_url, verify=False, timeout=10)\n soup = BeautifulSoup(resp.text, 'html.parser')\n articles = soup.select(article_sel)\n for art in articles:\n tag = art.select_one(title_sel)\n if not tag or not tag.get('href'):\n continue\n link = tag['href']\n url = link if link.startswith('http') else url_prefix + link\n title = tag.get_text(strip=True)\n dtag = art.select_one(date_sel)\n date = date_fmt_func(dtag.get_text(strip=True), source) if dtag else 'No date'\n body = fetch_article_content(url, source)\n results.append([title, body, date, url])\n logging.info(f'[{source}] Page {page} completed')\n time.sleep(1)\n except Exception as e:\n logging.error(f'[{source}] Page {page} error: {e}')\n return results\n\n# -------------------------------------------------\n# SSL 우회 세션 (일부 사이트 전용)\n# -------------------------------------------------\nclass SslAdapter(HTTPAdapter):\n def init_poolmanager(self, *args, **kwargs):\n ctx = ssl.create_default_context()\n ctx.set_ciphers('DEFAULT:@SECLEVEL=1')\n self.poolmanager = PoolManager(*args, ssl_context=ctx, **kwargs)\n\nsession = requests.Session()\nsession.mount('https://', SslAdapter())\nheaders = {'User-Agent': 'Mozilla/5.0', 'Accept-Language': 'ko-KR,ko;q=0.9'}\n\n# -------------------------------------------------\n# 사이트별 함수 (대한경제 제외)\n# -------------------------------------------------\nfetch_ikld = lambda s, e: fetch_articles(\n 'https://www.ikld.kr/news/articleList.html?page=',\n 'section.article-list-content div.table-row',\n 'div.list-titles.table-cell a.links',\n 'div.list-dated.table-cell', s, e, '국토일보', 'https://www.ikld.kr', format_date\n)\n\nfetch_conslove = lambda s, e: fetch_articles(\n 'http://www.conslove.co.kr/news/articleList.html?page=',\n 'section.article-list-content div.table-row',\n 'div.list-titles.table-cell a.links',\n 'div.list-dated.table-cell', s, e, '한건신문', 'http://www.conslove.co.kr', format_date\n)\n\nfetch_koscaj = lambda s, e: fetch_articles(\n 'https://www.koscaj.com/news/articleList.html?page=',\n 'section#section-list li',\n 'h2.titles a',\n 'em.info.dated', s, e, '전문건설신문', 'https://www.koscaj.com', format_date\n)\n\nfetch_engdaily = lambda s, e: fetch_articles(\n 'https://www.engdaily.com/news/articleList.html?page=',\n 'section.article-list-content div.table-row',\n 'a.links',\n 'div.list-dated.table-cell', s, e, '엔지니어링데일리', 'https://www.engdaily.com', format_date\n)\n\nfetch_cenews = lambda s, e: fetch_articles(\n 'http://www.cenews.kr/news/articleList.html?page=',\n 'section.article-list-content div.table-row',\n 'a.links',\n 'div.list-dated.table-cell', s, e, '건설이코노미뉴스', 'http://www.cenews.kr', format_date\n)\n\nfetch_engjournal = lambda s, e: fetch_articles(\n 'http://www.engjournal.co.kr/news/articleList.html?page=',\n 'section.article-list-content div.table-row',\n 'a.links',\n 'div.list-dated.table-cell', s, e, '공학저널', 'http://www.engjournal.co.kr', format_date\n)\n\nfetch_yna = lambda s, e: fetch_articles(\n 'https://www.yna.co.kr/news/',\n 'div.list-type038 li',\n 'a.tit-wrap',\n 'span.txt-time', s, e, '연합뉴스', 'https:', format_date\n)\n\nfetch_denews = lambda s, e: fetch_articles(\n 'http://www.denews.co.kr/news/articleList.html?page=',\n 'section.article-list-content div.table-row',\n 'div.list-titles.table-cell a.links',\n 'div.list-dated.table-cell', s, e, '디지털경제뉴스', 'http://www.denews.co.kr', format_date\n)\n\n\ndef fetch_aitimes(s, e):\n data = []\n base = 'https://www.aitimes.com/news/articleList.html?page='\n for p in range(s, e+1):\n resp = session.get(f\"{base}{p}\", headers=headers)\n soup = BeautifulSoup(resp.text, 'html.parser')\n for li in soup.select('ul.type1 li'):\n a = li.select_one('h4.titles a')\n if not a: continue\n url = a['href'] if a['href'].startswith('http') else 'https://aitimes.com'+a['href']\n art = BeautifulSoup(session.get(url, headers=headers).text, 'html.parser')\n body = ' '.join(p.get_text(strip=True) for p in art.select('article[itemprop=\"articleBody\"] p'))\n title = art.select_one('header.article-view-header h3.heading').get_text(strip=True)\n dli = art.select_one('div.info-group ul.infomation li:nth-of-type(2)')\n date = dli.get_text(strip=True).split('입력')[-1].strip() if dli else 'No date'\n data.append([title, body, date, url])\n time.sleep(random.uniform(1,2))\n return data\n\n\ndef fetch_hankyung(s, e):\n data = []\n base = 'https://www.hankyung.com/it?page='\n for p in range(s, e+1):\n resp = session.get(f\"{base}{p}\", headers=headers)\n soup = BeautifulSoup(resp.text, 'html.parser')\n for li in soup.select('ul.news-list li'):\n a = li.select_one('h3.news-tit a')\n if not a: continue\n url = a['href'] if a['href'].startswith('http') else 'https://www.hankyung.com'+a['href']\n art = BeautifulSoup(session.get(url, headers=headers).text, 'html.parser')\n title = art.select_one('h1.headline').get_text(strip=True)\n pub = art.select_one('span.txt-date').get_text(strip=True) if art.select_one('span.txt-date') else 'No date'\n body = ' '.join(p.get_text(strip=True) for p in art.select('div[itemprop=\"articleBody\"] p'))\n data.append([title, body, pub, url])\n time.sleep(random.uniform(2,5))\n return data\n\n# -------------------------------------------------\n# 데이터 수집 및 저장\n# -------------------------------------------------\nprint(\"Starting data collection from all sites...\")\n\nikld_data = fetch_ikld(1, 3)\nconslove_data = fetch_conslove(1, 2)\nkoscaj_data = fetch_koscaj(1, 1)\nengdaily_data = fetch_engdaily(1, 1)\ncenews_data = fetch_cenews(1, 1)\nengjournal_data = fetch_engjournal(1, 3)\nnyna_data = fetch_yna(1, 3)\ndenews_data = fetch_denews(1, 3)\naitimes_data = fetch_aitimes(1, 5)\nhankyung_data = fetch_hankyung(1, 5)\n\nall_data = (\n ikld_data + conslove_data + koscaj_data + engdaily_data +\n cenews_data + engjournal_data + nyna_data + denews_data +\n aitimes_data + hankyung_data\n)\n\ndf = pd.DataFrame(all_data, columns=['Title', 'Script', 'Date', 'URL'])\ndf.to_excel(\"comprehensive_article_metadata.xlsx\", index=False)\n\nlogging.info(\"Data collection complete and saved to comprehensive_article_metadata.xlsx\")\nprint(\"Data collection complete and saved to comprehensive_article_metadata.xlsx\")\nprint(f\"Total articles collected: {len(all_data)}\")\n" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 176, + -48 + ], + "id": "4c40dc3f-07d1-4061-b65d-562695c47254", + "name": "Code in Python" + }, + { + "parameters": { + "formTitle": "뉴스 수집", + "formDescription": "키워드를 중심으로 perplexity에서 관련 기사를 수집합니다.", + "formFields": { + "values": [ + { + "fieldLabel": "키워드", + "requiredField": true + }, + { + "fieldLabel": "수집 기간", + "fieldType": "dropdown", + "fieldOptions": { + "values": [ + { + "option": "당일" + } + ] + } + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.formTrigger", + "typeVersion": 2.5, + "position": [ + -112, + 432 + ], + "id": "dcd008de-2b5d-47a4-ad81-4687bf93264d", + "name": "키워드 입력(Trigger)", + "webhookId": "c17c3ace-123f-426e-b636-9f2ccf75a54c" + }, + { + "parameters": { + "aggregate": "aggregateAllItemData", + "destinationFieldName": "=data", + "include": "=본문 전체", + "options": {} + }, + "type": "n8n-nodes-base.aggregate", + "typeVersion": 1, + "position": [ + 1088, + 432 + ], + "id": "74ae43b0-b261-4fb2-9926-1ccc3ade5f56", + "name": "AI 분석을 위한 전처리(본문 추출)" + }, + { + "parameters": { + "modelId": { + "__rl": true, + "value": "models/gemini-2.5-flash", + "mode": "list", + "cachedResultName": "models/gemini-2.5-flash" + }, + "messages": { + "values": [ + { + "content": "=아래는 '{{ $('키워드 입력(Trigger)').first().json['키워드'] }}' 키워드 관련 뉴스 본문들입니다.\n\n{{ $json.data.map(item => item['본문 전체']).join('\\n\\n') }}\n\n위 내용을 바탕으로 주요 인사이트 3개를 아래 JSON 형식으로만 답해줘. 다른 말은 하지 마:\n[\n {\"제목\": \"인사이트 제목\", \"내용\": \"상세 내용\", \"링크\": \"관련 기사 URL\"},\n {\"제목\": \"인사이트 제목\", \"내용\": \"상세 내용\", \"링크\": \"관련 기사 URL\"},\n {\"제목\": \"인사이트 제목\", \"내용\": \"상세 내용\", \"링크\": \"관련 기사 URL\"}\n]" + } + ] + }, + "builtInTools": {}, + "options": {} + }, + "type": "@n8n/n8n-nodes-langchain.googleGemini", + "typeVersion": 1.1, + "position": [ + 1232, + 432 + ], + "id": "13eb0c70-acae-4431-a3e2-724fa0e1374d", + "name": "본문 분석(인사이트 3개 뽑기)", + "credentials": { + "googlePalmApi": { + "id": "evMMDN0o1ciE31vt", + "name": "Google Gemini(PaLM) Api account" + } + } + }, + { + "parameters": { + "jsCode": "const text = $json.content.parts[0].text;\nconst parsed = JSON.parse(text.replace(/```json|```/g, '').trim());\nreturn parsed.map((item, i) => ({\n json: {\n '#': i + 1,\n '인사이트': item.제목,\n '관련 내용': item.내용,\n '관련 링크': item.링크\n }\n}));" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1488, + 432 + ], + "id": "eecdd5a7-c247-410f-a643-0068ed8d00df", + "name": "뽑은 인사이트 정리하기" + }, + { + "parameters": { + "operation": "append", + "documentId": { + "__rl": true, + "value": "1wWTPdmC3-RXHi0ng6T6VcvIom_R6CdNkGFnB9eSqLlw", + "mode": "list", + "cachedResultName": "sample", + "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1wWTPdmC3-RXHi0ng6T6VcvIom_R6CdNkGFnB9eSqLlw/edit?usp=drivesdk" + }, + "sheetName": { + "__rl": true, + "value": 1131542344, + "mode": "list", + "cachedResultName": "sheet 2", + "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1wWTPdmC3-RXHi0ng6T6VcvIom_R6CdNkGFnB9eSqLlw/edit#gid=1131542344" + }, + "columns": { + "mappingMode": "defineBelow", + "value": { + "#": "={{ $json['#'] }}", + "인사이트": "={{ $json['인사이트'] }}", + "관련 내용": "={{ $json['관련 내용'] }}", + "링크": "={{ $json['관련 링크'] }}" + }, + "matchingColumns": [], + "schema": [ + { + "id": "#", + "displayName": "#", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + }, + { + "id": "인사이트", + "displayName": "인사이트", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + }, + { + "id": "관련 내용", + "displayName": "관련 내용", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + }, + { + "id": "링크", + "displayName": "링크", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + } + ], + "attemptToConvertTypes": false, + "convertFieldsToString": false + }, + "options": {} + }, + "type": "n8n-nodes-base.googleSheets", + "typeVersion": 4.7, + "position": [ + 1632, + 432 + ], + "id": "555e5573-64ca-457c-9ee8-cf26e1cd65b5", + "name": "저장하기(sheet2)", + "credentials": { + "googleSheetsOAuth2Api": { + "id": "4gOcyPEP0O8ViCLs", + "name": "Google Sheets account 2" + } + } + }, + { + "parameters": { + "url": "https://openapi.naver.com/v1/search/news.json", + "sendQuery": true, + "queryParameters": { + "parameters": [ + { + "name": "=query", + "value": "={{ $json['키워드'] }}" + }, + { + "name": "display", + "value": "12" + }, + { + "name": "sort", + "value": "=date" + } + ] + }, + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "X-Naver-Client-Id", + "value": "O3foIC9BjTO1co15Aw86" + }, + { + "name": "X-Naver-Client-Secret", + "value": "GM2xjQt2MJ" + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [ + 192, + 432 + ], + "id": "dff89381-1e63-443a-8d39-dcd0560c4c1a", + "name": "기사 수집(Naver API)" + }, + { + "parameters": { + "fieldToSplitOut": "items", + "options": {} + }, + "type": "n8n-nodes-base.splitOut", + "typeVersion": 1, + "position": [ + 336, + 432 + ], + "id": "39c09e4c-f8e3-4658-9b86-7708097a6484", + "name": "수집 정보 정리" + }, + { + "parameters": { + "url": "=https://r.jina.ai/{{ $json.link }}", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "Authorization", + "value": "Bearer jina_a72bde1404d14c2a94fd0c8b357cf795yFATC69lNjusqnhy5ymUhnqjBMNh" + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [ + 480, + 432 + ], + "id": "88a4882c-f6d1-4ce5-bbdc-c359bd7ec9da", + "name": "기사 본문 수집" + }, + { + "parameters": { + "mode": "runOnceForEachItem", + "jsCode": "const raw = $json.data || '';\n\nconst mcIdx = raw.indexOf('Markdown Content:');\nconst mdText = mcIdx !== -1 ? raw.substring(mcIdx + 17) : raw;\n\nconst lines = mdText.split('\\n');\nconst bodyLines = lines.filter(line => {\n const t = line.trim();\n return t.length > 50\n && !t.startsWith('#')\n && !t.startsWith('*')\n && !t.startsWith('[')\n && !t.startsWith('!')\n && !t.startsWith('|');\n});\n\nconst body = bodyLines.join(' ').substring(0, 8000);\n\nreturn {\n json: {\n title: $('수집 정보 정리').item.json.title,\n 발행일: $('수집 정보 정리').item.json.pubDate,\n url: $('수집 정보 정리').item.json.link,\n 주요내용: $('수집 정보 정리').item.json.description,\n 본문전체: body\n }\n};" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 624, + 432 + ], + "id": "06ed4bfa-5dee-46dc-8899-bced70618aaf", + "name": "본문 정리" + }, + { + "parameters": { + "operation": "append", + "documentId": { + "__rl": true, + "value": "1wWTPdmC3-RXHi0ng6T6VcvIom_R6CdNkGFnB9eSqLlw", + "mode": "list", + "cachedResultName": "sample", + "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1wWTPdmC3-RXHi0ng6T6VcvIom_R6CdNkGFnB9eSqLlw/edit?usp=drivesdk" + }, + "sheetName": { + "__rl": true, + "value": "gid=0", + "mode": "list", + "cachedResultName": "시트1", + "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1wWTPdmC3-RXHi0ng6T6VcvIom_R6CdNkGFnB9eSqLlw/edit#gid=0" + }, + "columns": { + "mappingMode": "defineBelow", + "value": { + "title": "={{ $json.title }}", + "url": "={{ $json.url }}", + "주요 내용": "={{ $json['주요내용'] }}", + "발행일": "={{ $json['발행일'] }}", + "구분": "={{ $itemIndex + 1 }}", + "본문 전체": "={{ $json['본문전체'] }}" + }, + "matchingColumns": [], + "schema": [ + { + "id": "구분", + "displayName": "구분", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + }, + { + "id": "title", + "displayName": "title", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + }, + { + "id": "발행일", + "displayName": "발행일", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + }, + { + "id": "url", + "displayName": "url", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + }, + { + "id": "주요 내용", + "displayName": "주요 내용", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + }, + { + "id": "본문 전체", + "displayName": "본문 전체", + "required": false, + "defaultMatch": false, + "display": true, + "type": "string", + "canBeUsedToMatch": true + } + ], + "attemptToConvertTypes": false, + "convertFieldsToString": false + }, + "options": {} + }, + "type": "n8n-nodes-base.googleSheets", + "typeVersion": 4.7, + "position": [ + 768, + 432 + ], + "id": "a042c1fa-e1e3-4ec2-8ac2-950141b875c7", + "name": "기사 저장 (제목, 발행일, url, 요약, 본문 전체)", + "credentials": { + "googleSheetsOAuth2Api": { + "id": "4gOcyPEP0O8ViCLs", + "name": "Google Sheets account 2" + } + } + } + ], + "pinData": {}, + "connections": { + "Message a model": { + "main": [ + [ + { + "node": "Split Out", + "type": "main", + "index": 0 + } + ] + ] + }, + "Split Out": { + "main": [ + [ + { + "node": "HTTP Request", + "type": "main", + "index": 0 + } + ] + ] + }, + "RSS Read": { + "main": [ + [ + { + "node": "HTTP Request1", + "type": "main", + "index": 0 + } + ] + ] + }, + "키워드 입력(Trigger)": { + "main": [ + [ + { + "node": "기사 수집(Naver API)", + "type": "main", + "index": 0 + } + ] + ] + }, + "AI 분석을 위한 전처리(본문 추출)": { + "main": [ + [ + { + "node": "본문 분석(인사이트 3개 뽑기)", + "type": "main", + "index": 0 + } + ] + ] + }, + "본문 분석(인사이트 3개 뽑기)": { + "main": [ + [ + { + "node": "뽑은 인사이트 정리하기", + "type": "main", + "index": 0 + } + ] + ] + }, + "뽑은 인사이트 정리하기": { + "main": [ + [ + { + "node": "저장하기(sheet2)", + "type": "main", + "index": 0 + } + ] + ] + }, + "기사 수집(Naver API)": { + "main": [ + [ + { + "node": "수집 정보 정리", + "type": "main", + "index": 0 + } + ] + ] + }, + "수집 정보 정리": { + "main": [ + [ + { + "node": "기사 본문 수집", + "type": "main", + "index": 0 + } + ] + ] + }, + "기사 본문 수집": { + "main": [ + [ + { + "node": "본문 정리", + "type": "main", + "index": 0 + } + ] + ] + }, + "본문 정리": { + "main": [ + [ + { + "node": "기사 저장 (제목, 발행일, url, 요약, 본문 전체)", + "type": "main", + "index": 0 + } + ] + ] + }, + "기사 저장 (제목, 발행일, url, 요약, 본문 전체)": { + "main": [ + [ + { + "node": "AI 분석을 위한 전처리(본문 추출)", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1", + "binaryMode": "separate", + "availableInMCP": false + }, + "versionId": "ae9131fb-9d1a-4827-928b-8a6f8d43b1bc", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "f05a5d847999236f5c88cdf334bbb894fc64f4ac70c6fb365f5a000dfb58a2b2" + }, + "id": "NgtFEf55fyLTGesY", + "tags": [] +} \ No newline at end of file diff --git a/n8n/n8n을 활용한 뉴스 기사 수집 Sample.hwp b/n8n/n8n을 활용한 뉴스 기사 수집 Sample.hwp new file mode 100644 index 0000000..d37af3e Binary files /dev/null and b/n8n/n8n을 활용한 뉴스 기사 수집 Sample.hwp differ