이상한 MYPI

이상한
접속 : 6930   Lv. 113

Category

Profile

Counter

  • 오늘 : 345 명
  • 전체 : 8354429 명
  • Mypi Ver. 0.3.1 β
[공부 - PG] 가격 변동 확인용 프로그램 수정 (1) 2021/05/23 PM 08:49

지난 주에 만들었던게 너무 대충 만들어서 조금만 덜 대충 만들었습니다..


프로그램이라고 오버해서 말하지만 어차피 파이선 스크립트



 

수정점

1. 메일서버 정보를 sqlite로 옮김

1. xpath등 파싱할 데이터를 sqlite로 옮겨서 가능한 범용적 처리 가능하게 함


이 이상 손 될거는 없어보이네요..

 

문제점은

1. 역시 예외 처리는 1도 없음

1. 서버 정보 소스에는 안넣었어도 sqlite의 보안처리가 없기 때문에 보안에는 큰 의미 없음..


이번 수정때문에 소스는 수정없이 넣어도 되겠네요..


우선 DB 바뀐거


SITE

파싱할 데이터를 집어 넣을 칼럼추가

img/21/05/23/17999089b06224d0.png

 

 ITEM

URL생성용 OPT의 필드명 좀 수정

OPT3 타입 잘 못지정한거 수정함

img/21/05/23/17999089d1d224d0.png

 

 메일 정보용 테이블

뭐 그냥 보면 무슨 뜻일지 알듯

img/21/05/23/1799908a219224d0.png

 

 

추가 항목은 이런식으로 넣음

img/21/05/23/1799908a4fc224d0.png

 

 


소스

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

import smtplib, ssl
import email.utils
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

import sqlite3

#import logging
#logging.basicConfig(level=logging.DEBUG, filename="test.log", format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')

options = Options()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
chrome_prefs = {}
options.experimental_options["prefs"] = chrome_prefs
chrome_prefs["profile.default_content_settings"] = {"images": 2}
chrome_prefs["profile.managed_default_content_settings"] = {"images": 2}
driver = webdriver.Chrome(executable_path="/usr/lib/chromium-browser/chromedriver", chrome_options=options)

dbPath = "./"
dbFileName = "PriceChk.sqlite3"
conn = sqlite3.connect(dbPath + dbFileName)

cur = conn.cursor()

SELECT_TEXT = "select B.ITEM_ID, B.NAME, A.SITE_TYPE, A.URL, A.URL_TYPE, B.URL_OPT1, B.URL_OPT2, B.URL_OPT3, "
SELECT_TEXT += "A.OBJ_TYPE_ONLYONE, A.OBJ_TYPE_ATTRIBUTE, A.OBJ_XPATH, A.OBJ_ATTRIBUTE, A.OBJ_TEXT_START, A.OBJ_TEXT_END "
SELECT_TEXT += "from SITE A, ITEM B where B.DEL=0 AND A.SITE_TYPE=B.SITE_TYPE"

dataList = cur.execute(SELECT_TEXT).fetchall()
for data in dataList:
    dataItemID = data[0]
    dataName = data[1]
    dataSiteType = data[2]
    dataUrl = data[3]
    dataUrlType = data[4]
    dataUrlOpt1 = data[5]
    dataUrlOpt2 = data[6] or ""
    dataUrlOpt3 = data[7] or ""

    dataObjTypeOnlyOne = data[8]
    dataObjTypeAttribute = data[9]
    dataObjXpath = data[10]
    dataObjAttribute = data[11]
    dataTextStart = data[12] or ""
    dataTextEnd = data[13] or ""
    
    url = ""
    if dataUrlType == 1:
        url = dataUrl.format(dataUrlOpt1)
    elif dataUrlType == 2:
        url = dataUrl.format(dataUrlOpt1, dataUrlOpt2)
    elif dataUrlType == 3:
        url = dataUrl.format(dataUrlOpt1, dataUrlOpt2, dataUrlOpt3)

    #print(url)
    driver.get(url)
    
    newPrice = ""
    if dataObjTypeOnlyOne == 1:
        targetObj = driver.find_element_by_xpath(dataObjXpath)
        tempPrice = ""
        if dataObjTypeAttribute == 1:
            tempPrice = targetObj.get_attribute(dataObjAttribute)
        else:
            tempPrice = targetObj.text
        newPrice = tempPrice[len(dataTextStart):len(tempPrice)-len(dataTextEnd)]
    else:
        for targetObj in driver.find_elements_by_xpath(dataObjXpath):
            tempPrice = ""
            if dataObjTypeAttribute == 1:
                tempPrice = targetObj.get_attribute(dataObjAttribute)
            else:
                tempPrice = targetObj.text
            if tempPrice.startswith(dataTextStart) and tempPrice.endswith(dataTextEnd):
                newPrice = tempPrice[len(dataTextStart):len(tempPrice)-len(dataTextEnd)]
                break
    
    print("{0}:{1}:{2}".format(dataItemID, dataName, newPrice))

    oldPriceSelect = cur.execute("select ITEM_ID, PRICE, DATE from DATA where ITEM_ID = ? order by DATE desc limit 1", (str(dataItemID),)).fetchone()
    oldPrice = ""
    if not oldPriceSelect is None:
        oldPrice = oldPriceSelect[1]

    if oldPrice != newPrice:
        cur.execute("insert into DATA ( ITEM_ID, PRICE, DATE ) VALUES (?, ?, datetime('now', 'localtime'))", (dataItemID, newPrice))

        mailInfo = cur.execute("select SMTP_URL, SMTP_PORT, SEND_MAIL_ADDRESS, SEND_MAIL_PASSWORD, RECEIVE_MAIL_ADDRESS from MAILINFO").fetchone()
        if mailInfo != None:
            fromaddr = mailInfo[2]
            toaddr = mailInfo[4]
            
            msgBody = "{0}의 가격 변경\n{1}→{2}\n{3}".format(dataName, oldPrice, newPrice, url)
            msg = MIMEMultipart()
            msg['From'] = email.utils.formataddr(('가격봇', fromaddr))
            msg['To'] = email.utils.formataddr(('너님', toaddr))
            msg['Subject'] = "{0}의 가격 변경".format(dataName)
            msg.attach(MIMEText(msgBody))

            id = fromaddr
            password = mailInfo[3]

            context = ssl.create_default_context()
            with smtplib.SMTP(mailInfo[0], mailInfo[1]) as server:
                server.ehlo()  # Can be omitted
                server.starttls(context=context)
                server.ehlo()  # Can be omitted
                server.login(id, password)
                server.sendmail(fromaddr, toaddr, msg.as_string())

conn.commit()
conn.close()
driver.close()
driver.quit()

 

소스 수정으로 이제 그냥 붙일 수 있네요...


뭐.. 어차피 자기 보존용이지만;;;;;

신고

 

물의보호막    친구신청

그래도 이런거 오픈해주시는 정성이 좋군용
X