@@ -191,6 +191,78 @@ async def get_user_solved_problems_from_solved_ac(baekjoon_id: str, target_probl
191191 return []
192192
193193
194+ async def check_problems_individual_queries (baekjoon_id : str , target_problems : List [int ], headers : dict ) -> List [int ]:
195+ """
196+ 각 문제마다 개별 query를 날려서 해결 여부 확인
197+ https://solved.ac/problems?query=s@{handle}+{problem_id}&page=1
198+
199+ 모의테스트처럼 문제 수가 적을 때 사용 (42페이지를 모두 조회할 필요 없음)
200+ """
201+ try :
202+ import urllib .parse
203+
204+ solved_problems = []
205+ target_set = set (target_problems )
206+
207+ logger .info (f"[개별 문제 확인] { baekjoon_id } - { len (target_problems )} 개 문제 개별 확인 시작" )
208+
209+ async with aiohttp .ClientSession (headers = headers ) as session :
210+ for problem_id in target_problems :
211+ # 각 문제마다 query: s@{handle}+{problem_id}
212+ query = f"s@{ baekjoon_id } +{ problem_id } "
213+ encoded_query = urllib .parse .quote (query )
214+ url = f"https://solved.ac/problems?query={ encoded_query } &page=1"
215+
216+ try :
217+ async with session .get (url ) as response :
218+ if response .status != 200 :
219+ logger .debug (f"[개별 문제 확인] { baekjoon_id } - 문제 { problem_id } : HTTP { response .status } " )
220+ await asyncio .sleep (0.2 )
221+ continue
222+
223+ html = await response .text ()
224+ soup = BeautifulSoup (html , 'html.parser' )
225+
226+ # "해당하는 문제가 없습니다" 메시지 확인
227+ no_problems_text = soup .find (string = re .compile (r'해당하는 문제가 없습니다|문제가 없습니다' ))
228+ if no_problems_text :
229+ logger .debug (f"[개별 문제 확인] { baekjoon_id } - 문제 { problem_id } : 미해결" )
230+ await asyncio .sleep (0.2 )
231+ continue
232+
233+ # 문제 번호가 결과에 있는지 확인
234+ problem_links = soup .find_all ('a' , href = re .compile (r'(?:www\.)?acmicpc\.net/problem/\d+|/problem/\d+' ))
235+ found = False
236+ for link in problem_links :
237+ href = link .get ('href' , '' )
238+ match = re .search (r'(?:www\.)?acmicpc\.net/problem/(\d+)|/problem/(\d+)' , href )
239+ if match :
240+ found_id = int (match .group (1 ) or match .group (2 ))
241+ if found_id == problem_id :
242+ solved_problems .append (problem_id )
243+ found = True
244+ logger .debug (f"[개별 문제 확인] { baekjoon_id } - 문제 { problem_id } : 해결됨" )
245+ break
246+
247+ if not found :
248+ logger .debug (f"[개별 문제 확인] { baekjoon_id } - 문제 { problem_id } : 미해결" )
249+
250+ await asyncio .sleep (0.2 ) # Rate limiting 방지
251+
252+ except Exception as e :
253+ logger .error (f"[개별 문제 확인] { baekjoon_id } - 문제 { problem_id } 확인 중 오류: { e } " )
254+ await asyncio .sleep (0.2 )
255+ continue
256+
257+ solved_problems = sorted (list (set (solved_problems )))
258+ logger .info (f"[개별 문제 확인] { baekjoon_id } - { len (solved_problems )} /{ len (target_problems )} 개 해결" )
259+ return solved_problems
260+
261+ except Exception as e :
262+ logger .error (f"[개별 문제 확인] 오류: { e } " , exc_info = True )
263+ return []
264+
265+
194266async def _check_problems_via_search_api (baekjoon_id : str , target_problems : List [int ], headers : dict ) -> List [int ]:
195267 """
196268 solved.ac 문제 검색 API를 사용하여 사용자가 푼 모든 문제를 페이지네이션으로 확인
0 commit comments