[FAQ] 전화번호부 사이트 크롤링
전화번호부 사이트 크롤링¶
- Q: 전화번호부 사이트를 검색하여 목록을 추출하고자 하는데, 데이터 전달이 되지 않습니다.
- A: 데이터를 인코딩 해주세요. 국내 사이트의 경우 종종 EUC-KR로 인코딩된 데이터만 수용하도록 설계된 경우가 있습니다.
http://fb.com/financedata¶
다음과 같은 검색 결과를 얻을 수 있다. (특정 지역 + 휴일진료하는 의료기관을 알 수 있다면 좋은 정보가 될 수 도 있을 듯)
euc-kr 인코딩 문제¶
다른 크롤링 방법과 크게 다르지 않다. 다만, 폼 데이터(requests.post()의 data 인자)로 서버에 전달해야 하는 값이 유니코드가 아니라 "euc-kr"이라는 점이 차이가 있다. (국내 사이트의 상당수가 이런 인코딩 이슈를 안고 있다)
빨간색 테두리 부분을 살펴보자. FormData 부분을 보면 이상한 문자열로 데이터가 구성되는 것을 볼 수 있는데. 16진수 데이터들이 URL인코딩된 데이터이다.
In [1]:
# searchWord:%C8%DE%C0%CF%C1%F8%B7%E1
# x:37.5640907
# y:126.9979403
# dong:
# city:%BC%AD%BF%EF
# gu:%C1%DF%B1%B8
# addr4:
# addr:%BC%AD%BF%EF+%C1%DF%B1%B8
from urllib.parse import quote, unquote
u = '%C8%DE%C0%CF%C1%F8%B7%E1'
print (unquote(u, encoding='euc-kr'))
u = '%BC%AD%BF%EF'
print (unquote(u, encoding='euc-kr'))
u = '%BC%AD%BF%EF+%C1%DF%B1%B8'
print (unquote(u, encoding='euc-kr'))
str(유니코드) → bytes(EUC-KR) → URL Quot¶
In [2]:
b = '휴일진료'.encode('euc-kr')
print( type(b) )
print( quote(b) )
URL Quot (EUC-KR) → str(유니코드)¶
In [3]:
u = '%C8%DE%C0%CF%C1%F8%B7%E1'
s = unquote(u, encoding='euc-kr')
print(type(s))
print(s)
해결책¶
해결책은 무척 간단하다. str(유니코드)를 EUC-KR로 인코딩을 해주면 된다.
str.encode('euc-kr')
크롤링과 한글 인코딩에 대한 조금 더 상세한 내용은 아래 포스팅을 참조하자.
In [4]:
import requests
url = 'http://www.isuperpage.co.kr/search.asp'
data = {
'searchWord': '휴일진료'.encode('euc-kr'),
'dong':''.encode('euc-kr'),
'city': '서울'.encode('euc-kr'),
'gu': '중구'.encode('euc-kr'),
}
r = requests.post(url, data=data)
r.text[:1000]
Out[4]:
In [5]:
from bs4 import BeautifulSoup
soup = BeautifulSoup(r.text, 'lxml')
search_result = soup.find('div', {'id':'search_result'})
In [6]:
lis = search_result.find_all('li')[2:]
for li in lis:
divs = li.find_all('div')
# div[0]
title = divs[0].a.text # 상호
spans = divs[0].find_all('span')
search = spans[1].text # 검색어
# div[1]
spans = divs[1].find_all('span')
phone = spans[0].text # 전화번호
addr = spans[1].text # 주소
addr_road = spans[2]['title'] # 도로명 주소
print( "%s, %s, %s, %s, %s" % (title, search, phone, addr, addr_road) )
댓글
Comments powered by Disqus