빠른 답변
2026년에 Python에서 Google 검색 결과를 어떻게 가져오나요?
Python에서 SERP API를 호출하고 반환되는 JSON을 읽으세요. google.com을 직접 가져오지 마세요. Google은 2025년 1월 17일부터 JavaScript를 요구했고 robots.txt는 /search을 금지합니다. SerpCrypto에서는 requests.get에서 https://serpcrypto.com/api/v1/search로의 한 번 호출이 유기적 결과, People Also Ask 등을 반환하며, 2026년 10월 기준 US$0.30/1K 검색부터 검색당 크레딧 하나입니다. KYC 없이 암호화폐로 결제하세요.
필요한 것
| Python | 3.9 이상 |
|---|---|
| 패키지 | 기본용 requests; 표용 pandas; async용 httpx |
| API 키 | SerpCrypto 대시보드에서 받아 SERPCRYPTO_API_KEY 환경 변수에 저장 |
| 엔드포인트 | GET https://serpcrypto.com/api/v1/search |
| 비용 | 1 크레딧 = 성공한 검색 요청 1건이며, 지원되는 모든 엔진에서 결과 한 페이지를 반환합니다. 실패한 요청은 과금되지 않습니다 |
| 가장 작은 팩 | US$7.50에 검색 10,000회; 크레딧은 만료되지 않음 |
google.com에 대한 requests.get이 더 이상 작동하지 않는 이유는 무엇인가요?
결과가 더 이상 일반 HTTP 클라이언트가 받는 HTML에 들어 있지 않기 때문입니다. 2025년 1월 17일 Google은 Search에 JavaScript를 요구하기 시작했으며, JavaScript가 봇으로부터 서비스를 보호하는 데 도움이 되고 JavaScript를 끈 사용자의 검색은 0.1% 미만이었다고 TechCrunch가 보도했습니다.
2026년 10월 22일에 확인한 Google의 robots.txt는 모든 user agent에 대해 Disallow: /search을 나열하기도 합니다. SERP API가 검색 실행과 페이지 파싱을 처리하고, Python 코드는 JSON만 다룹니다. 이것이 이 가이드의 나머지 부분에서 사용하는 접근 방식입니다.
첫 요청은 어떻게 하나요?
requests를 설치하고, 키를 환경 변수에 넣고, 국가와 언어와 함께 쿼리를 보내세요. 응답은 결과 페이지의 블록마다 키가 하나씩 있는 딕셔너리이며, organic_results에 순위가 매겨진 링크가 들어 있습니다.
키를 소스 코드에 두지 마세요. macOS와 Linux에서는 셸에서 export SERPCRYPTO_API_KEY=...; Windows PowerShell에서는 $env:SERPCRYPTO_API_KEY="...".
import os
import requests
API = "https://serpcrypto.com/api/v1/search"
KEY = os.environ["SERPCRYPTO_API_KEY"]
resp = requests.get(
API,
headers={"Authorization": "Bearer " + KEY},
params={"engine": "google", "q": "best hiking boots", "gl": "us", "hl": "en"},
timeout=60,
)
resp.raise_for_status()
results = resp.json()
for item in results.get("organic_results", []):
print(item["position"], item["title"])
print(" ", item["link"])
for q in results.get("people_also_ask", []):
print("PAA:", q["question"])
결과를 pandas DataFrame으로 어떻게 바꾸나요?
유기적 결과마다 행 하나를 만들고 쿼리를 옆에 두세요. DataFrame을 사용하면 정렬, 도메인별 필터링, CSV와 Excel로 내보내기가 쉬워집니다. 대부분의 결과에 date이 없는 등 누락된 필드는 오류 대신 빈 셀이 됩니다.
import os
from urllib.parse import urlparse
import pandas as pd
import requests
API = "https://serpcrypto.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]}
def organic_rows(query, gl="us", hl="en"):
params = {"engine": "google", "q": query, "gl": gl, "hl": hl}
resp = requests.get(API, headers=HEADERS, params=params, timeout=60)
resp.raise_for_status()
for r in resp.json().get("organic_results", []):
yield {
"query": query,
"position": r.get("position"),
"title": r.get("title"),
"domain": urlparse(r.get("link", "")).netloc,
"link": r.get("link"),
"snippet": r.get("snippet"),
}
queries = ["crm for small business", "invoice software", "time tracking app"]
df = pd.DataFrame([row for q in queries for row in organic_rows(q)])
print(df.groupby("domain").size().sort_values(ascending=False).head(10))
df.to_csv("serp_results.csv", index=False)
한 번에 여러 검색을 어떻게 실행하나요?
asyncio와 함께 httpx를 사용하고 세마포어로 동시에 진행 중인 요청 수를 제한하세요. 계정에는 대시보드에 표시되는 동시성 한도가 있으며, 이 한도를 넘지 않으면 429 오류를 피할 수 있습니다. 5처럼 작은 수로 시작해서 대시보드에 표시된 한도까지 올리세요.
import asyncio
import os
import httpx
API = "https://serpcrypto.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]}
LIMIT = asyncio.Semaphore(5)
async def search(client, query):
async with LIMIT:
resp = await client.get(API, params={"engine": "google", "q": query, "gl": "us", "hl": "en"})
resp.raise_for_status()
data = resp.json()
top = data.get("organic_results", [])[:3]
return query, [r["link"] for r in top]
async def main(queries):
async with httpx.AsyncClient(headers=HEADERS, timeout=60) as client:
for query, links in await asyncio.gather(*(search(client, q) for q in queries)):
print(query, links)
if __name__ == "__main__":
asyncio.run(main(["python web framework", "python orm", "python task queue"]))
10개가 넘는 결과를 받아서 저장하려면 어떻게 하나요?
page=2, page=3 등으로 다음 페이지를 요청하세요. page=10까지 가능합니다. 각 페이지는 검색 한 번, 크레딧 한 개입니다. Google이 2025년 9월에 num=100을(를) 더 이상 따르지 않게 된 이후 페이지당 약 10개의 유기적 결과만 제공하기 때문입니다.
각 원본 응답을 JSONL 파일의 한 줄로 저장하세요. 원본 JSON은 모든 블록을 보존하므로, 나중에 같은 검색에 다시 비용을 지불하지 않고도 새로운 질문에 답할 수 있습니다.
import json
import os
import requests
API = "https://serpcrypto.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]}
def fetch_pages(query, pages=3, path="serp.jsonl"):
with open(path, "a", encoding="utf-8") as out:
for page in range(1, pages + 1):
params = {"engine": "google", "q": query, "gl": "us", "hl": "en", "page": page}
resp = requests.get(API, headers=HEADERS, params=params, timeout=60)
resp.raise_for_status()
data = resp.json()
out.write(json.dumps(data, ensure_ascii=False) + "\n")
if not data.get("organic_results"):
break
fetch_pages("electric cargo bike", pages=3)
이 코드를 실행하면 비용이 얼마나 드나요?
이 예제의 각 호출은 검색 한 번입니다. 첫 번째 예제는 크레딧 1개, DataFrame 예제는 3개, JSONL 예제는 최대 3개입니다. 실패한 요청은 과금되지 않습니다.
2026년 10월 기준 검색 10,000회의 비용은 US$7.50이고, 검색 100,000회의 비용은 US$56.25입니다. 5,000,000회 검색에서는 요율이 US$0.30/1K 검색로 낮아집니다. 크레딧은 만료되지 않습니다. US$25 충전으로 BTC, USDT, USDC, ETH, SOL, LTC 결제하며, 신분증 업로드가 필요 없습니다. 가격을 참고하세요.
Python에서 Google 결과: 자주 묻는 질문
Google 결과 페이지에 BeautifulSoup을 사용할 수 있나요?
안정적으로는 어렵습니다. Google은 2025년 1월부터 JavaScript를 요구하므로 일반 클라이언트가 받는 HTML에는 결과가 담겨 있지 않고, Google의 robots.txt는 /search을(를) 허용하지 않습니다. 대신 SERP API는 파싱된 필드를 JSON으로 반환합니다.
SerpCrypto의 공식 Python 라이브러리가 있나요?
없습니다. API는 일반 HTTPS endpoint이므로 requests이나 httpx만 있으면 충분합니다. 이 페이지와 Python 문서 페이지의 예제는 복사해서 붙여 쓰는 코드이며, 배포된 패키지가 아닙니다.
다른 국가의 결과를 받으려면 어떻게 하나요?
gl을 국가 코드로, hl를 언어로 설정하세요. 예를 들어 프랑스라면 gl=fr과 hl=fr입니다. 도시를 지정하려면 location를 추가하세요. 위치 페이지에 자주 쓰는 코드가 정리되어 있습니다.
오류와 재시도를 어떻게 처리하나요?
raise_for_status()을 호출한 뒤 429, 502, 504 응답은 점점 늘어나는 지연 후에 재시도하세요. 실패한 요청은 과금되지 않습니다. 오류 페이지에 전체 재시도 함수가 있습니다.
같은 코드로 Bing 결과도 받을 수 있나요?
네. engine을 bing로 바꾸세요. 응답 구조는 동일하며, organic_results과 related_searches을 포함합니다.
출처 (3)
- Google이 Google 검색에 JavaScript를 요구하기 시작 — TechCrunch (2025-01-17)
- google.com robots.txt — Google (read 2026-10-22)
- Google이 순위 트래커를 쿼리당 500~1,000회 요청으로 몰아넣다 — PPC Land (2026-08-27)