bounce.mp3
0.50MB

- request와 Beautifulsoup를 이용한 USPS 택배 조회

 

 

request와 Beautifulsoup를 이용한 USPS 택배 조회

 

usps.com의 택배 조회를 하기 위한 웹 주소는 아래와 같다.

 

https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1=택배조회번호

 

찾고자 하는 택배조회 번호를 넣으면 아래와 같은 조회 페이지가 나온다.

 

 

이곳에서 빨간색 박스가 있는 부분을 이용하여 현재 택배 상태를 지속적으로 조회하는 프로그램을 만들어 본다.

 

 

 

1. request를 이용하여 웹 페이지 코드 받아오기

 

request를 이용하여 위 주소의 웹 페이지를 받아오는 코드는 아래와 같다.

result = requests.get("https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1=LW381151806CN")

 

하지만 usps.com의 택배 조회 사이트는 아래와 같은 에러가 발생한다.

Traceback (most recent call last):
  File "C:/JBMPA/lecture/uspstracking.py", line 3, in <module>
    result = requests.get("https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1=LW381151806CN")
  File "C:\Python37\lib\site-packages\requests\api.py", line 75, in get
    return request('get', url, params=params, **kwargs)
  File "C:\Python37\lib\site-packages\requests\api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Python37\lib\site-packages\requests\sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Python37\lib\site-packages\requests\sessions.py", line 668, in send
    history = [resp for resp in gen] if allow_redirects else []
  File "C:\Python37\lib\site-packages\requests\sessions.py", line 668, in <listcomp>
    history = [resp for resp in gen] if allow_redirects else []
  File "C:\Python37\lib\site-packages\requests\sessions.py", line 165, in resolve_redirects
    raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects, response=resp)
requests.exceptions.TooManyRedirects: Exceeded 30 redirects.

 

특정 웹 페이지의 도메인으로 접속했을 때, 웹 페이지는 다른 도메인으로 리다이렉트를 설정하는 경우가 있다. 이런 경우 웹 페이지의 리턴 값, 즉 response 값을 301이나 302를 받는다. 이와 같은 경우에 생기는 에러이다.

이 에러를 방지하기 위해서는 request로 웹 페이지를 접속할 때, 진짜 웹 브라우져인 것처럼 header 값을 만들어 주면 된다.

 

 headers = {
    'Accept-Encoding': 'gzip, deflate, sdch',
    'Accept-Language': 'en-US,en;q=0.8',
    'Upgrade-Insecure-Requests': '1',
   
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/605.1.15',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',

}

 

result = requests.get("https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1=LW381151806CN", headers = headers)

 

실질적으로는 headers의 속성에 웹 브라우져를 나타내는 'User-Agent' 값만 있어도 TooManyRedirects 에러를 피할 수 있다.

위 User-Agent는 "Chrome on Linux"을 의미한다. 실질적으로 Windows OS 체제를 사용한다고 하더라도  request를 통해 웹 페이지는 Linux기반의 크롬 브라우져가 접속했다고 인식한다.

User-Agent에 대한 다양한 정보는 아래 사이트를 참고한다.

https://developers.whatismybrowser.com/useragents/explore/

 

 

 

2. 웹 페이지를 소스 분석

 

현재 택배 상태를 나타내는 빨간색 박스 안의 내용이 어떤 html 코드안에 들어있는지 코드 보기를 하여 확인한다.

 

 

html 코드를 살펴보면 Status에 관련된 코드는 위 그림의 빨간색 박스속의 코드이다.

따라서 <div class="delivery_status"> 나 <div class='status_feed'> 부분을 이용하여 지속적으로 택배 배송 상태를 읽어오는 코드를 작성해 본다.

 

 

 

3. 소스 코드

 

import requests
import datetime
from bs4 import BeautifulSoup
from time import sleep
from playsound import playsound

 

# playsound 모듈을 이용하여 wav, mp3 파일을 플레이한다. bounce.mp3 시계탑 종소리
def soundcomplete():
    # False - background
    playsound("./sound/bounce.mp3", False)

 

# 웹 페이지에 웹 브라우져가 접근 한 것처럼 헤더 파일을 정의해준다.
headers = {
    'Accept-Encoding': 'gzip, deflate, sdch',
    'Accept-Language': 'en-US,en;q=0.8',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/605.1.15',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',

}

# 택배 조회 url

uspsurl = "https://tools.usps.com/go/TrackConfirmAction?qtc_tLabels1=LW381151806CN"

 

# 반복을 위한 변수
deliverycheck = True

 

while deliverycheck:
    result = requests.get(
uspsurl , headers = headers)
    html = result.text

 

    BS = BeautifulSoup(html, "html.parser")

 

    # 내부 html이 변경될 경우 에러 방지

    try:

        # devlivery_status 클래스의 div를 찾는다.
        ds = BS.find('div', {'class':'delivery_status'})

 

        # 현재 배송 상태를 조회하기 위해 strong 태그안의 text를 저장한다.
        status = ds.strong.text
    
        # 배송 상태 안내를 위한 텍스트 문구 저장
        statustext = ds.find('div', {'class':'status_feed'}).find('p', {'class':'important'}).text

 

        # 화면에 표시하기 위한 현재 시간
        now = datetime.datetime.now()

 

        # 현재 시간과 배송 상태를 print 해준다.
        print(now.strftime("%Y-%m-%d %H:%M:%S"), statustext)

 

        # 만약 배송 상태가 "In-Transit"이 아닐 때는, deliverycheck를 False로 한다, 즉 while loop를 멈춘다.
   
    # sondcomplete() 실행시켜, 소리로 안내를 받는다.
        if status != "In-Transit":
            soundcomplete()
            deliverycheck = False

 

    except:

        # 에러 표시

        print(now.strftime("%Y-%m-%d %H:%M:%S"), "Error")

 

    # 120초를 쉬었다가 실행한다. 즉, while문은 2분에 한번씩 실행된다.
    sleep(120)

 

 

 

 

4. 실행된 결과

 

2분에 한번씩 체크하여 화면에 표시해준다. 만약 배송조회 상태가 변경되면 종소리가 울리며 프로그램이 종료될 것이다.

 

 

 

 

+ Recent posts