programming

GS 편의점 택배 배송조회 여러건 크롤링 하기


by Kitle · 2020. 07. 05.



안녕하세요. 기트리 입니다.

요즘 회사에서 업무 자동화니 RPA니 자동화에 대한 관심 많으시죠.

반복적인 작업은 요즘 대부분 컴퓨터(기계)들이 대처하고 있죠.

특히 업무적으로 다량의 택배를 보내거나 하는 경우도 많은데, 배송 조회는 한건 한건 해야 하는 번거로움이 있죠.

이부분을 오늘은 자동적으로 해 보겠습니다.

필요한 선수 지식

html + python + requests + crawling(bs4) 으로 진행하겠습니다.


1. 환경 구성

python 개발 환경은 구성되어 있다고 가정하겠습니다.

파이썬 프로젝트 만드시고 가상환경 만드시고 필요한 패키지들 설치합니다.

pip install requests

pip install bs4

두개를 설치 합니다.


2. 구조 분석

2-1. 요청 url 확인하기

GS Postbox 택배 사이트에서 배송조회를 해봅니다.

배송조회 주소는 https://www.cvsnet.co.kr/reservation-inquiry/delivery/index.do 이군요.

그러면 실제 가지고 있는 송장 번호로 조회를 해봅니다.

https://www.cvsnet.co.kr/reservation-inquiry/delivery/index.do?dlvry_type=domestic&invoice_no=송장번호(12자리)&reservedNo=&rtnUrl=%2Freservation-inquiry%2Fdelivery%2Findex.do%3Fdlvry_type%3Ddomestic%26invoice_no%3D%26srch_type%3D01&srch_type=01 

라는 주소로 요청하게 됩니다.

뒤에 여러가지 쿼리스트링이 붙었지만 없어도 조회하는데 문제가 없습니다.

따라서 불필요한 쿼리 스트링을 제거하고 다시 조회해 봅니다. 우리는 결과만 나오면 되니까요.

https://www.cvsnet.co.kr/reservation-inquiry/delivery/index.do?dlvry_type=domestic&invoice_no=

여러번 해본 결과 결국 위의 주소 뒤에 송장 번호만 바꿔가며 조회하면 된다는 것을 알았습니다.

2-2 구조 확인하기
크롬등을 이용해 개발자 모드로 갑니다.
그리고 결과 부분을 클릭해 봅니다.
class가 txt로 되어있는 부분에 결과가 모이는 것 같습니다. 패턴을 파악해보니, 가장 최신 결과가 가장 위에 뜨는 것을 볼 수 있습니다.

결국 택배를 받았는지 안받았는지는 마지막 배송상태만 알면 되므로 마지막 배송상태를 추출해 봅니다.

따라서 모든 class가 txt인 데이터를 찾아서 첫번째 값을 추출하면 됩니다. (물론 다른방법도 있습니다)

3. 실제 구현
구현 해보겠습니다.
다음과 같이 진행됩니다.
1) 원하는 송장번호 리스트 만들기 (보통 택배사에서 줍니다)
  txt파일로 숫자 12자리로만 된 것을 한줄씩 만들어 저장합니다.

2) 송장번호 파일을 파이썬에서 한줄씩 읽어 list로 만들기.
  리스트로 불러올때 '' [] 등 불필요한 값이 들어가는 것은 문자열 처리로 제거합니다.

3) 택배조회시 고정 Url + 송장번호 를 바꿔가며 반복문으로 조회하기, 조회시 마지막 결과만 가져오기
 + 조회결과를 결과 파일로 저장합니다.

4. 코드

from bs4 import BeautifulSoup
import requests
import os
import datetime

INVOICE_LIST_DIR ='/송장리스트가 있는 폴더로 변경해주세요'
f = open("invoice_list.txt")

invoice_list = []

try:
for line in f:
# 한줄씩 처리하는 코드
oneline = str(line.split())
invoice_list.append(oneline[2:-2])

finally:
f.close()

baseurl = 'https://www.cvsnet.co.kr/reservation-inquiry/delivery/index.do?dlvry_type=domestic&invoice_no='
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.3239.132 Safari/537.36'}

with open(os.path.join(INVOICE_LIST_DIR, 'post_result.txt'), 'w+') as f:
for invoice in invoice_list:
html = requests.get(baseurl+invoice, headers=headers).text
soup = BeautifulSoup(html, 'html.parser')
historylists = soup.find_all(class_="txt")
result = historylists[0].get_text()
today = datetime.datetime.today()
s = today.strftime('%Y-%m-%d %H:%M:%S')
f.write(str(result) + ' 업데이트(조회) 시간: ' + str(s) + '\n')

5. 결과 확인

결과 출력도 잘 되네요.


6. 한계

웹사이트의 구조가 바뀌면 해당 코드는 동작하지 않습니다. 동작을 안하는 경우 웹사이트 구조가 바뀌었는지 체크합니다.

*짧은 시간 과도한 조회는 트래픽을 유발 합니다. 의도치 않게 택배사사이트를 공격하는 꼴이 되니 소량 정보 조회에 이용하시고 다량 조회가 필요한 경우는 시간 텀을 두어 조회하시기 바랍니다. 위 소스코드는 학습용으로 사용하시고 실제 사용시 무한루프, 다량 건 조회 등은 유의하여 사용하시기 바랍니다.