From c25fc1f25dea4b295ea58a0283fc07c11e05876e Mon Sep 17 00:00:00 2001 From: ened Date: Wed, 2 Aug 2023 22:04:02 +0900 Subject: [PATCH] Collect news title and write to json file --- .../Sources/Domestic/News/DomesticNews.swift | 25 +++++++-- KissMeConsole/Sources/KissConsole+News.swift | 51 +++++++++++++++++++ KissMeConsole/Sources/KissConsole.swift | 38 +++++++++++++- KissMeConsole/Sources/test.swift | 2 +- .../KissMeConsole.xcodeproj/project.pbxproj | 4 ++ 5 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 KissMeConsole/Sources/KissConsole+News.swift diff --git a/KissMe/Sources/Domestic/News/DomesticNews.swift b/KissMe/Sources/Domestic/News/DomesticNews.swift index 83ae60a..1a1a463 100644 --- a/KissMe/Sources/Domestic/News/DomesticNews.swift +++ b/KissMe/Sources/Domestic/News/DomesticNews.swift @@ -66,14 +66,12 @@ public struct DomesticNews { "mid": "sec", "listType": "title", "date": date.yyyyMMdd, - "page": page, + "page": String(page), ] } public var responseDataLoggable: Bool { true } public var traceable: Bool { true } public var session: URLSession { DomesticNews.session } - - public var result: KResult? = nil @@ -114,6 +112,9 @@ public struct DomesticNews { // TODO: articleUrl 에서 get param 만 추려냄. return [:] } + public var responseDataLoggable: Bool { true } + public var traceable: Bool { true } + public var session: URLSession { DomesticNews.session } public var result: KResult? = nil @@ -136,6 +137,12 @@ extension DomesticNews { public let title: String public let press: String public let url: URL + + public init(title: String, press: String, url: URL) { + self.title = title + self.press = press + self.url = url + } } public struct NewsArticle: Codable { @@ -146,6 +153,16 @@ extension DomesticNews { public let lastTime: String public let content: String public let url: URL + + public init(title: String, press: String, author: String, authorId: Int, lastTime: String, content: String, url: URL) { + self.title = title + self.press = press + self.author = author + self.authorId = authorId + self.lastTime = lastTime + self.content = content + self.url = url + } } static public func collectList(day: Date, tps: UInt64 = 1) async throws -> [NewsTitle] { @@ -220,7 +237,7 @@ extension DomesticNews { func getTitles(day: Date, page: Int) async throws -> ([NewsTitle], [Int]) { return try await withUnsafeThrowingContinuation { continuation in - let request = NaverNewsListRequest(date: day, page: 1) + let request = NaverNewsListRequest(date: day, page: page) request.query { result in switch result { case .success(let result): diff --git a/KissMeConsole/Sources/KissConsole+News.swift b/KissMeConsole/Sources/KissConsole+News.swift new file mode 100644 index 0000000..046bae4 --- /dev/null +++ b/KissMeConsole/Sources/KissConsole+News.swift @@ -0,0 +1,51 @@ +// +// KissConsole+News.swift +// KissMeConsole +// +// Created by ened-book-m1 on 2023/08/02. +// + +import Foundation +import KissMe + + +struct NewsList: Codable { + let list: [DomesticNews.NewsTitle] +} + + +extension KissConsole { + + static func newsListUrl(day: String) -> URL { + let subPath = "data-news/\(day)" + let subFile = "\(subPath)/list.json" + + let fileUrl = URL.currentDirectory().appending(path: subFile) + createSubpath(subPath) + return fileUrl + } + +// static func newsArticleUrl(day: String) -> URL { +// let subPath = "data-news/\(day)" +// let subFile = "\(subPath)/" +// } + + func writeNewsList(_ list: NewsList, day: Date) throws { + let listJson = KissConsole.newsListUrl(day: day.yyyyMMdd) + + let jsonData = try JSONEncoder().encode(list) + try jsonData.write(to: listJson, options: .atomic) + } + + func readNewsList(day: Date) throws -> NewsList { + let listJson = KissConsole.newsListUrl(day: day.yyyyMMdd) + + let data = try Data(contentsOf: listJson, options: .uncached) + let newsList = try JSONDecoder().decode(NewsList.self, from: data) + return newsList + } + + func writeNewsArticle(_ article: DomesticNews.NewsArticle, title: DomesticNews.NewsTitle, day: Date) throws { +// let articleJson = KissConsole.newsArticleUrl(day: day.yyyyMMdd) + } +} diff --git a/KissMeConsole/Sources/KissConsole.swift b/KissMeConsole/Sources/KissConsole.swift index 8368917..3f6067d 100644 --- a/KissMeConsole/Sources/KissConsole.swift +++ b/KissMeConsole/Sources/KissConsole.swift @@ -1225,11 +1225,47 @@ extension KissConsole { private func onNews(_ args: [String]) async { - // 특정 날짜의 뉴스 목록을 가져옴. + guard args.count == 1, let day = args[0].yyyyMMdd_toDate else { + print("Missing day") + return + } + do { + let list = try await DomesticNews.collectList(day: day) + let obj = NewsList(list: list) + try writeNewsList(obj, day: day) + print("Success \(day.yyyyMMdd) total: \(list.count)") + } catch { + print(error) + } } private func onNewsAll(_ args: [String]) { +// guard args.count == 1, let day = args[0].yyyyMMdd_toDate else { +// print("Missing day") +// return +// } + let day = "20230801".yyyyMMdd_toDate! + do { + let obj = try readNewsList(day: day) + print("Success \(day.yyyyMMdd) total: \(obj.list.count)") + + if let title = obj.list.first { + let semaphore = DispatchSemaphore(value: 0) + Task { + do { + let article = try await DomesticNews.getArticle(title.url) + print("\(article)") + } catch { + print(error) + } + semaphore.signal() + } + semaphore.wait() + } + } catch { + print(error) + } // 특정 날짜의 뉴스 목록 & 뉴스 기사를 가져옴. } } diff --git a/KissMeConsole/Sources/test.swift b/KissMeConsole/Sources/test.swift index 03a7d51..a059280 100644 --- a/KissMeConsole/Sources/test.swift +++ b/KissMeConsole/Sources/test.swift @@ -406,7 +406,7 @@ func test_request_naver_news_list() { do { let list = try await DomesticNews.collectList(day: day) for item in list { - print("\(item.title) :: \(item.press) :: \(item.url.absoluteString)") + print("\(item.title) :: \(item.press) :: \(item.url)") } } catch { print(error) diff --git a/projects/macos/KissMeConsole.xcodeproj/project.pbxproj b/projects/macos/KissMeConsole.xcodeproj/project.pbxproj index 8f9aa16..f3a280e 100644 --- a/projects/macos/KissMeConsole.xcodeproj/project.pbxproj +++ b/projects/macos/KissMeConsole.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 349327F72A20E3E300097063 /* Foundation+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349327F62A20E3E300097063 /* Foundation+Extensions.swift */; }; 349843212A242AC900E85B08 /* KissConsole+CSV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349843202A242AC900E85B08 /* KissConsole+CSV.swift */; }; 34D3680D2A280801005E6756 /* KissConsole+Candle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D3680C2A280801005E6756 /* KissConsole+Candle.swift */; }; + 34EC4D1F2A7A7365002F947C /* KissConsole+News.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34EC4D1E2A7A7365002F947C /* KissConsole+News.swift */; }; 34EE76862A1C391B009761D2 /* KissMe.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341F5EDB2A0A8C4600962D48 /* KissMe.framework */; }; 34EE76872A1C391B009761D2 /* KissMe.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 341F5EDB2A0A8C4600962D48 /* KissMe.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 34F190132A4441F00068C697 /* KissConsole+Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F190122A4441F00068C697 /* KissConsole+Test.swift */; }; @@ -57,6 +58,7 @@ 3498431E2A24287600E85B08 /* KissMeConsoleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KissMeConsoleTests.swift; sourceTree = ""; }; 349843202A242AC900E85B08 /* KissConsole+CSV.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KissConsole+CSV.swift"; sourceTree = ""; }; 34D3680C2A280801005E6756 /* KissConsole+Candle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KissConsole+Candle.swift"; sourceTree = ""; }; + 34EC4D1E2A7A7365002F947C /* KissConsole+News.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KissConsole+News.swift"; sourceTree = ""; }; 34F190122A4441F00068C697 /* KissConsole+Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KissConsole+Test.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -101,6 +103,7 @@ 349843202A242AC900E85B08 /* KissConsole+CSV.swift */, 3435A7F32A35B4D000D604F1 /* KissConsole+Price.swift */, 3435A7F12A35A8A900D604F1 /* KissConsole+Investor.swift */, + 34EC4D1E2A7A7365002F947C /* KissConsole+News.swift */, 34F190122A4441F00068C697 /* KissConsole+Test.swift */, 349327F62A20E3E300097063 /* Foundation+Extensions.swift */, ); @@ -194,6 +197,7 @@ 348168492A2F92AC00A50BD3 /* KissContext.swift in Sources */, 3435A7F42A35B4D000D604F1 /* KissConsole+Price.swift in Sources */, 34F190132A4441F00068C697 /* KissConsole+Test.swift in Sources */, + 34EC4D1F2A7A7365002F947C /* KissConsole+News.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };