From c53307462e0d19d16d397df46a0c067a7b99865a Mon Sep 17 00:00:00 2001 From: rkdgusdnr99 <112935900+rkdgusdnr99@users.noreply.github.com> Date: Thu, 30 May 2024 21:40:21 +0900 Subject: [PATCH 1/8] =?UTF-8?q?Naver=20=ED=81=AC=EB=A1=A4=EB=A7=81=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 2 + .../aimju/controller/CrawlingController.java | 25 +++++++++++ .../Crawling/Service/CrawlingService.java | 44 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 backend/src/main/java/hello/aimju/controller/CrawlingController.java create mode 100644 backend/src/main/java/hello/aimju/image/Crawling/Service/CrawlingService.java diff --git a/backend/build.gradle b/backend/build.gradle index 3ed75bda..e1596020 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -40,6 +40,8 @@ dependencies { implementation 'org.hibernate.validator:hibernate-validator-cdi:6.2.0.Final' implementation 'io.github.flashvayne:chatgpt-spring-boot-starter:1.0.4' + + implementation 'org.jsoup:jsoup:1.15.3' } tasks.named('test') { diff --git a/backend/src/main/java/hello/aimju/controller/CrawlingController.java b/backend/src/main/java/hello/aimju/controller/CrawlingController.java new file mode 100644 index 00000000..14f2941c --- /dev/null +++ b/backend/src/main/java/hello/aimju/controller/CrawlingController.java @@ -0,0 +1,25 @@ +package hello.aimju.controller; + +import hello.aimju.image.Crawling.Service.CrawlingService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; + +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api") +public class CrawlingController { + + private final CrawlingService crawlingService; + + @GetMapping("/menu-image/{query}") + public String fetchImage(@PathVariable("query") String query) { + try { + return crawlingService.fetchImageUrl(query); + } catch (IOException e) { + e.printStackTrace(); + return "Error: Unable to fetch image"; + } + } +} diff --git a/backend/src/main/java/hello/aimju/image/Crawling/Service/CrawlingService.java b/backend/src/main/java/hello/aimju/image/Crawling/Service/CrawlingService.java new file mode 100644 index 00000000..11728353 --- /dev/null +++ b/backend/src/main/java/hello/aimju/image/Crawling/Service/CrawlingService.java @@ -0,0 +1,44 @@ +package hello.aimju.image.Crawling.Service; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +@Service +public class CrawlingService { + + public String fetchImageUrl(String query) throws IOException { + // 쿼리 인코딩 + String encodedQuery = URLEncoder.encode(query, StandardCharsets.UTF_8.toString()); + System.out.println("Original query: " + query); + System.out.println("Encoded query: " + encodedQuery); + + // URL 생성 + String url = "https://search.naver.com/search.naver?ssc=tab.image.all&where=image&sm=tab_jum&query=" + query; + System.out.println("URL: " + url); + + // 페이지 가져오기 + Document doc = Jsoup.connect(url) + .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36") + .get(); + System.out.println("Document fetched"); +// System.out.println(doc.outerHtml()); // 페이지 생김새 출력 + + Elements imgElements = doc.select("div.keyword_tag_area._fe_image_tab_tag_root img"); // 이미지 태그 선택 + if (!imgElements.isEmpty()) { + Element imgElement = imgElements.first(); // 첫 번째 이미지 태그 선택 + String imgUrl = imgElement.attr("src"); // 이미지 태그의 src 속성 값 가져오기 + System.out.println("Image URL: " + imgUrl); + return imgUrl; + } else { + System.out.println("No image element found"); + return null; + } + } +} \ No newline at end of file From 0c634216aded37bb80d436fe3a3787b325d668c5 Mon Sep 17 00:00:00 2001 From: rkdgusdnr99 <112935900+rkdgusdnr99@users.noreply.github.com> Date: Thu, 30 May 2024 21:41:09 +0900 Subject: [PATCH 2/8] =?UTF-8?q?=EB=A0=88=EC=8B=9C=ED=94=BC=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=EC=8B=9C=20=EB=A0=88=EC=8B=9C=ED=94=BC=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=EB=8F=84=20=EA=B0=99=EC=9D=B4=20=EB=B3=B4?= =?UTF-8?q?=EC=97=AC=EC=A4=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/recommend/page.tsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/frontend/src/app/recommend/page.tsx b/frontend/src/app/recommend/page.tsx index a2e46641..1206d322 100755 --- a/frontend/src/app/recommend/page.tsx +++ b/frontend/src/app/recommend/page.tsx @@ -37,6 +37,8 @@ export default function Recommend() { const [uploadButtonEnabled, setUploadButtonEnabled] = useState(true); const [yesOrNoButtonEnabled, setYesOrNoButtonEnabled] = useState(true); const [recipeButtonEnabled, setRecipeButtonEnabled] = useState(true); + const [imageUrl, setImageUrl] = useState(''); + const router = useRouter(); const handleRoutingMain = () => { @@ -103,6 +105,17 @@ export default function Recommend() { menu: menu, ingredients: middleIngredients.split(', '), }; + + try { + const routingPoint = '/api/menu-image/' + menu + console.log(routingPoint) + const response = await axios.get(routingPoint); // menu 값 사용 + const imageUrl = response.data; + setImageUrl(imageUrl); + console.log(imageUrl) + } catch (error) { + console.error('Error fetching image:', error); + } try { const response = await axios.post('/api/recommendation-recipe-str', request); setRecipeString(response.data); @@ -403,6 +416,13 @@ export default function Recommend() {
+ {imageUrl && ( +
+
+ 검색된 이미지 {/* 이미지 너비를 w-64로 조정 */} +
+
+ )}

{menu}의 레시피는 다음과 같습니다.

{recipeString}

From d6aee496ff2d81ce8035443a1298d242d02ad33b Mon Sep 17 00:00:00 2001 From: rkdgusdnr99 <112935900+rkdgusdnr99@users.noreply.github.com> Date: Thu, 30 May 2024 23:04:42 +0900 Subject: [PATCH 3/8] =?UTF-8?q?=EB=A0=88=EC=8B=9C=ED=94=BC=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=ED=81=AC=EB=A1=A4=EB=A7=81=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=20*=20=EB=A7=8C=EA=B0=9C?= =?UTF-8?q?=EC=9D=98=20=EB=A0=88=EC=8B=9C=ED=94=BC=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=EB=A7=81=20=20*=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EC=A2=80=EB=8D=94=20=EA=B9=94=EB=81=94=ED=95=98?= =?UTF-8?q?=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image/Crawling/Service/CrawlingService.java | 16 +++++++--------- frontend/src/app/recommend/page.tsx | 6 ++++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/hello/aimju/image/Crawling/Service/CrawlingService.java b/backend/src/main/java/hello/aimju/image/Crawling/Service/CrawlingService.java index 11728353..5cc609c0 100644 --- a/backend/src/main/java/hello/aimju/image/Crawling/Service/CrawlingService.java +++ b/backend/src/main/java/hello/aimju/image/Crawling/Service/CrawlingService.java @@ -3,7 +3,6 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; import org.springframework.stereotype.Service; import java.io.IOException; @@ -20,7 +19,7 @@ public String fetchImageUrl(String query) throws IOException { System.out.println("Encoded query: " + encodedQuery); // URL 생성 - String url = "https://search.naver.com/search.naver?ssc=tab.image.all&where=image&sm=tab_jum&query=" + query; + String url = "https://www.10000recipe.com/recipe/list.html?q=" + encodedQuery; System.out.println("URL: " + url); // 페이지 가져오기 @@ -28,14 +27,13 @@ public String fetchImageUrl(String query) throws IOException { .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36") .get(); System.out.println("Document fetched"); -// System.out.println(doc.outerHtml()); // 페이지 생김새 출력 - Elements imgElements = doc.select("div.keyword_tag_area._fe_image_tab_tag_root img"); // 이미지 태그 선택 - if (!imgElements.isEmpty()) { - Element imgElement = imgElements.first(); // 첫 번째 이미지 태그 선택 - String imgUrl = imgElement.attr("src"); // 이미지 태그의 src 속성 값 가져오기 - System.out.println("Image URL: " + imgUrl); - return imgUrl; + // 이미지 URL 추출 + Element imgElement = doc.select("div.common_sp_thumb img").first(); + if (imgElement != null) { + String imageUrl = imgElement.attr("src"); + System.out.println("Image URL: " + imageUrl); + return imageUrl; } else { System.out.println("No image element found"); return null; diff --git a/frontend/src/app/recommend/page.tsx b/frontend/src/app/recommend/page.tsx index 1206d322..c2bbb674 100755 --- a/frontend/src/app/recommend/page.tsx +++ b/frontend/src/app/recommend/page.tsx @@ -112,7 +112,7 @@ export default function Recommend() { const response = await axios.get(routingPoint); // menu 값 사용 const imageUrl = response.data; setImageUrl(imageUrl); - console.log(imageUrl) + console.log(imageUrl); } catch (error) { console.error('Error fetching image:', error); } @@ -419,7 +419,9 @@ export default function Recommend() { {imageUrl && (
- 검색된 이미지 {/* 이미지 너비를 w-64로 조정 */} +
+ My Image +
)} From 89cd89d859ab4472a77b8ee0e4155f64194904ca Mon Sep 17 00:00:00 2001 From: SproutMj Date: Fri, 31 May 2024 11:24:10 +0900 Subject: [PATCH 4/8] =?UTF-8?q?=ED=94=84=EB=A1=A0=ED=8A=B8=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/boards/page.tsx | 42 +++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/boards/page.tsx b/frontend/src/app/boards/page.tsx index 64850864..9f901d31 100755 --- a/frontend/src/app/boards/page.tsx +++ b/frontend/src/app/boards/page.tsx @@ -38,15 +38,15 @@ type Board = { export default function Board() { const [currentPage, setCurrentPage] = useState(0); const [totalPages, setTotalPages] = useState(0); - const [searchKeyword, setSearchKeyword] = useState(null); const [boards, setBoards] = useState([]); const {getState} = useUserStore; const ownBoard = useBoardStore((state) => state.ownBoard); + const [searchKeyword, setSearchKeyword] = useState(''); - const getBoards = async (page = 0, searchKeyword = null)=>{ + const getBoards = async (page = 0)=>{ try { let response; - if(searchKeyword === null){ + if(searchKeyword === ''){ response = await axios.get('/api/boards', { params: { page: page, @@ -76,10 +76,10 @@ export default function Board() { } }; - const getOwnBoards = async (page = 0, searchKeyword = null) => { + const getOwnBoards = async (page = 0) => { try { let response; - if (searchKeyword === null) { + if (searchKeyword === '') { response = await axios.get('/api/boards/current-user', { params: { page: page, @@ -119,26 +119,50 @@ export default function Board() { const handlePrevPage = () => { if (ownBoard === 1) { - getOwnBoards(currentPage - 1, searchKeyword); + getOwnBoards(currentPage - 1); } else { - getBoards(currentPage - 1, searchKeyword); + getBoards(currentPage - 1); } setCurrentPage(currentPage - 1); } const handleNextPage = () => { if (ownBoard === 1) { - getOwnBoards(currentPage + 1, searchKeyword); + getOwnBoards(currentPage + 1); } else { - getBoards(currentPage + 1, searchKeyword); + getBoards(currentPage + 1); } setCurrentPage(currentPage + 1); } + const handleSearchChange = (e: React.ChangeEvent) => { + setSearchKeyword(e.target.value); + }; + return ( <>
+
{ + event.preventDefault() + if (ownBoard === 1) { + getOwnBoards(); + } else { + getBoards(); + } + }} className="mb-6 flex items-center justify-center"> + + +
{boards.map((board, index)=>( From a12f53b5c90382801f85162f4decfea9aa19c3f8 Mon Sep 17 00:00:00 2001 From: SproutMj Date: Fri, 31 May 2024 12:28:44 +0900 Subject: [PATCH 5/8] =?UTF-8?q?=EB=A3=A8=ED=8A=B8=20=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/favicon.ico | Bin 25931 -> 0 bytes frontend/src/app/favicon.png | Bin 0 -> 13354 bytes frontend/src/app/layout.tsx | 7 +++++-- 3 files changed, 5 insertions(+), 2 deletions(-) delete mode 100644 frontend/src/app/favicon.ico create mode 100644 frontend/src/app/favicon.png diff --git a/frontend/src/app/favicon.ico b/frontend/src/app/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 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 LrJugUA?W`A8`#=m diff --git a/frontend/src/app/favicon.png b/frontend/src/app/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..32f5c84cf70bbdb47aab309bae35d61f7846cb97 GIT binary patch literal 13354 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 Q0|liZqas}`X%zT>0KPt-0ssI2 literal 0 HcmV?d00001 diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 3314e478..f29e3637 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -5,8 +5,11 @@ import "./globals.css"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "AI 명종원", + description: "당신의 재료로 레시피를 추천합니다.", + icons: { + icon: "/favicon.png", + }, }; export default function RootLayout({ From 30d26589ed105181cb940eb273601f6422fd459c Mon Sep 17 00:00:00 2001 From: rkdgusdnr99 <112935900+rkdgusdnr99@users.noreply.github.com> Date: Fri, 31 May 2024 13:55:54 +0900 Subject: [PATCH 6/8] =?UTF-8?q?ChatType=EC=97=90=20ImageUrl=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/hello/aimju/chat/chat_message/domain/ChatType.java | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/main/java/hello/aimju/chat/chat_message/domain/ChatType.java b/backend/src/main/java/hello/aimju/chat/chat_message/domain/ChatType.java index 5064a7ac..60593b38 100644 --- a/backend/src/main/java/hello/aimju/chat/chat_message/domain/ChatType.java +++ b/backend/src/main/java/hello/aimju/chat/chat_message/domain/ChatType.java @@ -6,5 +6,6 @@ public enum ChatType { menu, ingredient, recipe, + imageUrl, link } \ No newline at end of file From fd23a7d06c3b87105678c3b6bb0bccc0f19e2dca Mon Sep 17 00:00:00 2001 From: rkdgusdnr99 <112935900+rkdgusdnr99@users.noreply.github.com> Date: Fri, 31 May 2024 13:56:45 +0900 Subject: [PATCH 7/8] =?UTF-8?q?ImageUrl=20=EC=A0=80=EC=9E=A5=20=EB=B0=8F?= =?UTF-8?q?=20=EB=B6=88=EB=9F=AC=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/app/chatroom/[chatroomId]/page.tsx | 24 ++++++++++++------- frontend/src/app/recommend/page.tsx | 3 +++ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/chatroom/[chatroomId]/page.tsx b/frontend/src/app/chatroom/[chatroomId]/page.tsx index 52441c4a..85c95528 100644 --- a/frontend/src/app/chatroom/[chatroomId]/page.tsx +++ b/frontend/src/app/chatroom/[chatroomId]/page.tsx @@ -64,12 +64,17 @@ export default function ChatRoom({ params }: { params: { chatroomId: number } }) ...message, content: `${menuString} 검색하기` }; + } else if (message.chatType === "imageUrl") { + return { + ...message, + content: `Chat Image` + }; } else { return message; } }); - setChatMessages(messagesWithLinks); + }) .catch(error => { alert('비정상적인 접근입니다.'); @@ -86,9 +91,16 @@ export default function ChatRoom({ params }: { params: { chatroomId: number } }) {chatMessages.map((message, index) => ( -

+
+ {message.isUser !== 1 && ( + + + ML + + )}
-
+
{message.isUser === 1 && ( @@ -96,12 +108,6 @@ export default function ChatRoom({ params }: { params: { chatroomId: number } }) YU )} - {message.isUser !== 1 && ( - - - ML - - )}
))}
diff --git a/frontend/src/app/recommend/page.tsx b/frontend/src/app/recommend/page.tsx index c2bbb674..d46f43fa 100755 --- a/frontend/src/app/recommend/page.tsx +++ b/frontend/src/app/recommend/page.tsx @@ -153,6 +153,9 @@ export default function Recommend() { addChatMessage(`해당 재료로 만들 수 있는 음식은 다음과 같습니다.\n${menus}\n어떤 재료의 음식의 레시피를 보시겠습니까?`, 0, 'message'); addChatMessage(`${menu}`, 1, 'menu'); addChatMessage(`${menu}의 레시피는 다음과 같습니다.`, 0, 'message'); + if (imageUrl !== null && imageUrl !== undefined) { + addChatMessage(imageUrl, 0, 'imageUrl'); + } addChatMessage(`${recipeString}`, 0, 'recipe'); addChatMessage(`${recipeLink}`, 0,'link'); }, [recipeLink]); From a88b1cb7e2e7cc48aa806cad1917382d9e060823 Mon Sep 17 00:00:00 2001 From: rkdgusdnr99 <112935900+rkdgusdnr99@users.noreply.github.com> Date: Fri, 31 May 2024 13:57:46 +0900 Subject: [PATCH 8/8] =?UTF-8?q?=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?=20*=20@PathVariable=20=ED=98=95=ED=83=9C=EB=8A=94=20string?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B0=9B=EC=9D=8C.=20number=20=ED=98=95?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=A0=84=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/app/boards/writing/[recipeId]/page.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/boards/writing/[recipeId]/page.tsx b/frontend/src/app/boards/writing/[recipeId]/page.tsx index ae96abed..d361aaf8 100644 --- a/frontend/src/app/boards/writing/[recipeId]/page.tsx +++ b/frontend/src/app/boards/writing/[recipeId]/page.tsx @@ -15,7 +15,9 @@ export default function PostWriting({ params }: { params: { recipeId: number } } const [selectedRecipe, setSelectedRecipe] = useState(null); // 선택된 레시피 ID useEffect(() => { - if (params.recipeId !== 0) { + const recipeId = Number(params.recipeId); + if (recipeId !== 0) { + console.log(params.recipeId); const fetchRecipeContent = async () => { try { const response = await axios.get(`/api/recipe/${params.recipeId}`);