ChatGPT에 HTML 넣기 힘드신가요? 클로드(Claude)를 써보세요

Claude를 활용하여 ChatGPT에 크림(Kream)의 HTML을 입력하고, 이를 기반으로 실시간 차트를 크롤링하는 방법을 알아보세요.

클로드(Claude)로 한정판 거래 플랫폼, 크림 (Kream : https://kream.co.kr)의 실시간 차트를 크롤링하는 예제를 준비했습니다.

1. 클로드(Claude)란 무엇인가?

notion image
Claude(클로드)는 오픈AI 직원들이 설립하고 구글의 강력한 지원을 받고 있는 인공지능 스타트업 Anthropic의 AI 챗봇 서비스입니다. 클로드 2는 2023년 7월 11일 발표되었으며, 약 3달 뒤인 10월 17일 한국에도 출시되었습니다. 클로드는 한국어 채팅은 물론, 최대 10MB 크기의 PDF, TXT, CSV 파일을 최대 5개까지 첨부할 수 있는 기능을 제공합니다. 프롬프트에서는 10만 개의 토큰을 지원하며 GPT-4(최대 32,768개)보다 훨씬 많은 토큰을 입력할 수 있다는 특징이 있습니다.
 
 

2. Claude로 HTML 분석하기

이번에는 Kream의 실시간 차트에 있는 가격 변동 정보를 크롤링 해보겠습니다.
notion image
상품 리스트를 가지고 있는 <ul> 태그의 HTML을 복사하여 분석을 요청해보겠습니다.
이전 ChatGPT로 완성하는 크롤링 봇 포스팅에서, GPT-4는 토큰 개수가 문제였습니다. GPT-4로 해당 HTML을 분석할 수 있는지 볼까요?
notion image
역시 토큰 수 제한에 걸려 처리할 수 없습니다.
클로드는 어떨까요?
notion image
먼저, 클로드는 HTML을 txt 파일로 받아서 분석하게 됩니다.
분석 결과를 보면, 상품 정보 뿐만 아니라 HTML 태그 정보, 어떤 라이브러리를 사용했는지까지 분석해주네요. 분석 결과를 바탕으로 어떤 정보를 수집할 수 있는지 확인할 수 있겠습니다.
 
 

3. Claude로 웹 데이터 추출하기

이제 본격적으로 Claude에게 데이터 추출을 위한 코드를 질문해보겠습니다.

3.1. 프롬프트 작성

다음과 같이 프롬프트를 입력하였습니다.
셀레니움으로 웹 페이지 데이터를 추출하고자 해. 언어는 Python을 사용해줘. 위 HTML에서 상품 이미지 URL, 상품명, 모델 번호, 사이즈, 가격, 가격 변동, 가격 변동 비율을 가져와줘. 위 항목은 모두 필수 데이터이므로 해당 데이터가 없다면 나에게 어떤 데이터를 찾을 수 없는지 오류 메시지를 전달해야 해. 모든 HTML element는 xpath로 찾아줘. 위 조건을 가지고 JSON 형식으로 데이터를 출력해줘.

3.2. 1차 응답

notion image
위 사진에서 볼 수 있듯이 셀레니움으로 xpath를 찾아 데이터를 가져오는 코드를 작성해줍니다.
그러나 최신 버전의 셀레니움은 find_element_by_xpath를 지원하지 않기 때문에 다음과 같이 수정을 요청했습니다.
내 셀레니움 버전에서는 `find_element_by_xpath`를 사용할 수 없어. `By`를 import해서 `find_element`로 요소를 찾도록 수정해줘.

3.3. 2차 응답

notion image
find_elementBy를 사용하도록 수정되었습니다.
다음은 Claude가 작성해준 코드 전체입니다.
from selenium import webdriver from selenium.webdriver.common.by import By import json driver = webdriver.Chrome() driver.get("<https://www.example.com>") products = [] items = driver.find_elements(By.XPATH, "//ul[@class='trading-items-container']/li") for item in items: try: img_url = item.find_element(By.XPATH, ".//picture/img").get_attribute("src") except: img_url = "Image URL not found" try: name = item.find_element(By.XPATH, ".//div[contains(@class,'name')]").text except: name = "Name not found" try: code = item.find_element(By.XPATH, ".//div[contains(@class,'style-code')]").text except: code = "Code not found" try: size = item.find_element(By.XPATH, ".//div[contains(@class,'option')]").text except: size = "Size not found" try: price = item.find_element(By.XPATH, ".//div[contains(@class,'current-price')]").text except: price = "Price not found" try: change = item.find_element(By.XPATH, ".//div[contains(@class,'change-price')]/span").text except: change = "Price change not found" try: change_pct = item.find_element(By.XPATH, ".//div[contains(@class,'change-percent')]").text.split()[0] except: change_pct = "Change percentage not found" product = { "image": img_url, "name": name, "code": code, "size": size, "price": price, "price_change": change, "price_change_pct": change_pct } products.append(product) print(json.dumps(products, indent=2)) driver.quit()
위 코드를 보면 예외처리부터 json 형식 출력까지 프롬프트의 요구사항들을 모두 만족하는 것을 볼 수 있습니다.

3.4. 1차 수정하기

우리는 여기서 크롬 드라이버 설정만 수정하면 될 것 같습니다. 패키지 import부터 크롬 브라우저를 띄우는 데까지의 코드를 다음과 같이 변경하였습니다.
import json from selenium import webdriver from selenium.webdriver.chrome.service import Service as ChromeService from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.common.by import By url = "<https://kream.co.kr/trading-chart>" driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install())) driver.get(url)

3.5. 1차 실행

자, 이제 모두 준비가 된 것 같으니 실행해볼까요?
[ { "image": "<https://kream-phinf.pstatic.net/MjAyMzA0MDNfMTE1/MDAxNjgwNDkxOTQ4NjQ0.W-mLA596MM6US4gSI6jNsJ9NhCbIeUR5mg0qxQ6p_AUg.Ec1REyClrXQ38dSM40zZhVidrYf0gxBsnc7C1SqK71kg.JPEG/a_e78ed04e3a1948a09a7b26bff5b27634.jpg?type=m>", "name": "Nike x Peaceminusone LS T-Shirt Black (DR0098-010)", "code": "DR0098-010", "size": "M", "price": "152,000", "price_change": "\\u25b2", "price_change_pct": "+1.3%" }, { "image": "<https://kream-phinf.pstatic.net/MjAyMTAxMjBfNTAg/MDAxNjExMTIyMzAzMTY2.0QpenidH075iEa1_gVzZTKOxJPiB8W6KyX4YmiELcfIg.ydUN0Aq9T8nWA5frqrsbwnbFfsNMNHDx6ezU5WxGAfQg.PNG/p_28c110281b3f4e109e30a6247d503e2a.png?type=m>", "name": "Nike Dunk Low Pro Premium Medium Curry", "code": "DD1390-100", "size": "255", "price": "107,000", "price_change": "\\u25b2", "price_change_pct": "+0.9%" }, { "image": "<https://kream-phinf.pstatic.net/MjAyMTAzMDVfMjQz/MDAxNjE0OTE0NzIzMTQ4.tsuFUJtHGm4g4KE5EDikVMScORptOQqIB7afi1Nz2Qwg.sftz3YQOuw48xpNSJa1tV4uEsz5iU4mjIvpllgHWEn8g.PNG/p_8f7b72adbc924b5bbf7c670d55865e6b.png?type=m>", "name": "Adidas Samba OG Cloud White", "code": "B75806", "size": "215", "price": "130,000", "price_change": "\\u25b2", "price_change_pct": "+0.8%" } ]
<div data-v-4f90d828="" class="change-price up" style="color: rgb(241, 87, 70);"> <span data-v-4f90d828="" class="arrow">▲</span> <span data-v-4f90d828="">27,000</span> </div>
거의 모든 정보를 성공적으로 가져왔으나, 위와 같은 HTML 구조 때문에 에 해당하는 \\u25b2 문자만 가져오고 변동액은 가져오지 못한 것으로 보입니다.

3.6. 2차 수정

변동액도 가져올 수 있도록 다음과 같이 수정해줍니다:
try: change = item.find_element(By.XPATH, ".//div[contains(@class,'change-price')]").text.replace("\\u25bc", "-").replace("\\u25b2", "+") except: change = "Price change not found"

3.7. 2차 실행

다시 실행한 결과입니다:
[ { "image": "<https://kream-phinf.pstatic.net/MjAyMTA3MzBfNTYg/MDAxNjI3NjI3OTg5ODM5.p-9pRcc3cQ_eaTl7UZdCmPJz8Astbjg2N6_HkEhLrHsg.ekjxXxJ-kcnoaZC6gCQH_-KBCUJORPTRC791UZ_C3ukg.PNG/p_e1ef5e002eda49adb7f5d0c8a41f798d.png?type=m>", "name": "Jordan 1 x Travis Scott x Fragment Retro Low OG SP Military Blue", "code": "DM7866-140", "size": "260", "price": "1,875,000", "price_change": "+27,000", "price_change_pct": "+1.5%" }, { "image": "<https://kream-phinf.pstatic.net/MjAyMzA0MDNfMTE1/MDAxNjgwNDkxOTQ4NjQ0.W-mLA596MM6US4gSI6jNsJ9NhCbIeUR5mg0qxQ6p_AUg.Ec1REyClrXQ38dSM40zZhVidrYf0gxBsnc7C1SqK71kg.JPEG/a_e78ed04e3a1948a09a7b26bff5b27634.jpg?type=m>", "name": "Nike x Peaceminusone LS T-Shirt Black (DR0098-010)", "code": "DR0098-010", "size": "M", "price": "152,000", "price_change": "+2,000", "price_change_pct": "+1.3%" }, { "image": "<https://kream-phinf.pstatic.net/MjAyMjEwMTJfMjQ3/MDAxNjY1NTYyODI3ODMw.YeSueVotfq5mgVXlQIVeV-uL_Q2otMk6nkvlbG2rHncg.vMJPWgosd9OjOn-s75jjEnjk44sB1gNqftQSN8CEkTAg.PNG/a_b2325461062d47e2887459a3e6928d88.png?type=m>", "name": "Adidas Puffylette Core Black", "code": "GY4559", "size": "265", "price": "78,000", "price_change": "+1,000", "price_change_pct": "+1.3%" } ]
이제는 변동액과 그 방향도 제대로 알려주는 것 같네요.
 
 

4. 결론

이렇게 Claude를 활용해서 크림 실시간 차트 크롤러를 만들어보았습니다. Claude에는 최대 10MB의 파일을 첨부할 수 있어 긴 HTML도 분석할 수 있었습니다. ChatGPT에게 크롤러를 만들어 달라고 요청하려면 HTML의 크기를 줄여야 하지만, Claude는 긴 HTML도 문제없이 처리하는 모습을 보여줬습니다. 답변 속도는 ChatGPT에 비해 느리지만, 답변에서의 아쉬움은 없었습니다. 결론적으로, 웹 크롤러를 만들기에는 ChatGPT보다 Claude가 더 유용하다고 생각됩니다.