해당 코드는 solved.ac API를 사용하였습니다.
백준의 모든 문제를 가져와야 하는 일이 있어 코드를 작성하였다.
requests의 경우에 크롤링 하는 경우에 html을 가져오는(?) 형식으로 많이 사용하였는데
API를 가져올 수도 있다.
[python] REST API 호출에서 해당 코드를 읽어볼 수 있고 이를 조금 고치면 사용할 수 있다.
해당 코드의 구조는 이러하다.
- 크롤링할 페이지 전달
- requests 모듈을 통해 정보 가져옴
- str을 json으로 변경한 후 item만 분리
- 모든 item을 반복하며 필요한 정보만 가져옴(문제 번호, 타이틀, 태그)
- 모든 정보를 전역 변수에 저장
- 1 ~ 5를 반복문이 끝날 때 까지 반복하며 마지막에는 csv파일로 저장.
해당 API의 1분, 10분당 즉 시간에 대한 호출 제한을 몰라서 아주 최소한의 횟수로 선택하였다.
기본적으로 한글을 저장하는 상황이라면 메모리를 더 잡아먹는다.
TEXT와 같은 타입에선 길이가 곧 메모리이기 때문에 이를 줄이는 것이 더 좋다고 생각했다.
"", [], 와 같은 기호들을 제거하기 위해 배열이 아닌 문자열을 사용했다.
그리고 영어 태그, 이름을 가져오기 위해서는 가져오는 정보의 위치를 바꾸면 된다.
import requests, time, json, pandas as pd
idx, input_hash, input_title, solve, input_tag = [], [], [], [], []
def appending(hash, title, tags):
idx.append(None)
input_hash.append(hash)
input_title.append(title)
solve.append(None)
input_tag.append(tags)
def crawl(page):
url = "https://solved.ac/api/v3/search/problem"
querystring = {"query": " ", "page": f"{page}"}
headers = {"Content-Type": "application/json"}
response = requests.request("GET", url, headers=headers, params=querystring)
temp = dict()
temp["item"] = json.loads(response.text).get("items")
for item in temp["item"]:
hash = int(item.get("problemId")) * 1000
title = item.get("titleKo")
tags = ""
info = item.get("tags")
length = len(info)
for idx, tag in enumerate(info):
temp_tag = tag.get("displayNames")
tags += temp_tag[1].get("short")
if idx == length - 1:
continue
tags += " "
appending(hash, title, tags)
def make_csv():
df = pd.DataFrame({"PROBLEM_ID" : idx, "TITLE_NM" : input_title, "TAGS_NM" : input_tag, "SOLVED_USR" : solve, "HASH_ID" : input_hash})
df.to_csv("problem.csv", index=False, encoding="utf8")
def main():
for i in range(1, 250):
print(f"crawling {i} page now still {249 - i} to go")
crawl(i)
time.sleep(12)
make_csv()
if __name__ == "__main__":
main()