Python 은 Selenium 아 날로 그 브 라 우 저 자동 조작 기능 을 사용 합 니 다.
사이트 에서 데 이 터 를 추출 할 때 많은 사이트 에서 반 파충류 처 리 를 한 것 을 발견 할 수 있다.예 를 들 어 JS 암호 화,Ajax 암호 화,반 Debug 등 방법 은 요청 을 통 해 데 이 터 를 얻 는 것 과 페이지 에 보 여 주 는 내용 이 완전히 다르다.이때 Selenium 기술 을 사용 하여 탐색 기의 조작 을 모 의 한 다음 에 데 이 터 를 얻는다.본 고 는 간단 한 예 를 들 어 Python 이 Tkinter 와 Selenium 을 결합 하여 브 라 우 저의 시 뮬 레이 션 을 하 는 것 을 요약 하고 공유 하 는 것 만 배 울 수 있 으 며 부족 한 점 이 있 으 면 지적 해 주 십시오.
셀 레 니 움 이 뭐야?
Selenium 은 웹 프로그램 테스트 에 사용 되 는 도구 입 니 다.Selenium 테스트 는 브 라 우 저 에서 직접 실 행 됩 니 다.마치 실제 사용자 가 조작 하 는 것 과 같 습 니 다.지원 하 는 브 라 우 저 는 IE(7,8,9,10,11),Mozilla Firefox,Safari,Google Chrome,Opera 등 이다.Selenium 은 윈도,리 눅 스,IOS 등 다양한 운영 체 제 를 지원 하 며,안 드 로 이 드 지원 이 필요 하 다 면 특별한 selenium 이 필요 하 다.본 고 는 주로 IE 11 브 라 우 저 를 예 로 들 었 다.
Selenium 설치
pip install selenium 을 통 해 설치 하면 되 며 속도 가 느 리 면 국내 미 러 로 설치 할 수 있 습 니 다.
지식 에 관련되다
프로그램 이 비록 작 지만 파악 해 야 할 Html,JavaScript,CSS 등 기초 지식 을 제외 하고 본 사례 와 관련 된 Python 관련 지식 은 매우 많 습 니 다.구체 적 으로 다음 과 같 습 니 다.
Selenium 단일 원소 획득(예:findelement_by_xpath)와 원소 그룹 가 져 오기(예:findelements_by_xpath)두 가지 방식.
Selenium 요소 가 포 지 셔 닝 되면 요소 에 값 을 부여 하거나 해당 하 는 이벤트 작업 을 할 수 있 습 니 다(예:click).
스 레 드 를 사용 하 는 과정 에서 스 레 드 의 동기 화 를 확보 하기 위해 이 예 는 스 레 드 잠 금 을 사 용 했 습 니 다.예 를 들 어 threading.Lock().
열 을 put 를 통 해 스 택 을 누 르 고 get 을 통 해 스 택 을 나 갑 니 다.qsize()를 통 해 현재 열 요소 의 개 수 를 가 져 옵 니 다.
Python 의 로 그 는 모두 6 가지 등급 으로 NOTSET,DEBUG,INFO,WARN,ERROR,FATAL,CRITICAL 이다.
예제 효과 도
본 사례 는 주로 특정한 배 치 된 상품 ID 에 대해 윤 문 을 하고 물건 이 있 는 지 감시 하 며 물건 이 있 으 면 카 트 에 가입 하고 물건 이 없 으 면 계속 윤 문 을 한다.아래 그림 과 같다.
핵심 코드
본 사례 의 가장 핵심 적 인 코드 는 바로 Selenium 을 이용 하여 사이트 의 모 의 조작 을 하 는 것 이다.다음 과 같다.
class Smoking:
""" Smoking """
#
__driver: webdriver = None
#
__cfg_info: dict = {}
#
__log_helper: LogHelper = None
#
__work_path: str = ''
#
__running: bool = False
#
__no_stock = 'Currently Out of Stock'
#
__wait_sec = 2
def __init__(self, work_path, cfg_info, log_helper: LogHelper):
""" """
self.__cfg_info = cfg_info
self.__log_helper = log_helper
self.__work_path = work_path
self.__wait_sec = int(cfg_info['wait_sec'])
# 2, 2
self.__wait_sec = (2 if self.__wait_sec < 2 else self.__wait_sec)
def checkIsExistsById(self, id):
""" ID """
try:
i = 0
while self.__running and i < 3:
if len(self.__driver.find_elements_by_id(id)) > 0:
break
else:
time.sleep(self.__wait_sec)
i = i + 1
return len(self.__driver.find_elements_by_id(id)) > 0
except BaseException as e:
return False
def checkIsExistsByName(self, name):
""" """
try:
i = 0
while self.__running and i < 3:
if len(self.__driver.find_elements_by_name(name)) > 0:
break
else:
time.sleep(self.__wait_sec)
i = i + 1
return len(self.__driver.find_elements_by_name(name)) > 0
except BaseException as e:
return False
def checkIsExistsByPath(self, path):
""" xpath """
try:
i = 0
while self.__running and i < 3:
if len(self.__driver.find_elements_by_xpath(path)) > 0:
break
else:
time.sleep(self.__wait_sec)
i = i + 1
return len(self.__driver.find_elements_by_xpath(path)) > 0
except BaseException as e:
return False
def checkIsExistsByClass(self, cls):
""" class """
try:
i = 0
while self.__running and i < 3:
if len(self.__driver.find_elements_by_class_name(cls)) > 0:
break
else:
time.sleep(self.__wait_sec)
i = i + 1
return len(self.__driver.find_elements_by_class_name(cls)) > 0
except BaseException as e:
return False
def checkIsExistsByLinkText(self, link_text):
""" LinkText """
try:
i = 0
while self.__running and i < 3:
if len(self.__driver.find_elements_by_link_text(link_text)) > 0:
break
else:
time.sleep(self.__wait_sec)
i = i + 1
return len(self.__driver.find_elements_by_link_text(link_text)) > 0
except BaseException as e:
return False
def checkIsExistsByPartialLinkText(self, link_text):
""" LinkText """
try:
i = 0
while self.__running and i < 3:
if len(self.__driver.find_elements_by_partial_link_text(link_text)) > 0:
break
else:
time.sleep(self.__wait_sec)
i = i + 1
return len(self.__driver.find_elements_by_partial_link_text(link_text)) > 0
except BaseException as e:
return False
# def waiting(self, *locator):
# """ """
# # self.__driver.switch_to.window(self.__driver.window_handles[1])
# Wait(self.__driver, 60).until(EC.visibility_of_element_located(locator))
def login(self, username, password):
""" """
# 5.
self.__driver.find_element_by_link_text(' ').click()
# 6.
#
# self.waiting((By.ID, "email"))
if self.checkIsExistsById('email'):
self.__driver.find_element_by_id('email').send_keys(username)
self.__driver.find_element_by_id('password').send_keys(password)
# 7.
self.__driver.find_element_by_id('sign-in').click()
def working(self, item_id):
""" """
while self.__running:
try:
#
if self.checkIsExistsById('string'):
self.__driver.find_element_by_id('string').clear()
self.__driver.find_element_by_id('string').send_keys(item_id)
self.__driver.find_element_by_id('string').send_keys(Keys.ENTER)
#
xpath = "//div[@class='specialty-header search']/div[@class='specialty-description']/div[" \
"@class='gt-450']/span[2] "
if self.checkIsExistsByPath(xpath):
count = int(self.__driver.find_element_by_xpath(xpath).text)
if count < 1:
time.sleep(self.__wait_sec)
self.__log_helper.put(' item id =' + item_id + ' ')
continue
else:
time.sleep(self.__wait_sec)
self.__log_helper.put(' item id2 =' + item_id + ' ')
continue
#
xpath1 = "//div[@class='product-list']/div[@class='product']/div[@class='price-and-detail']/div[" \
"@class='price']/span[@class='noStock'] "
if self.checkIsExistsByPath(xpath1):
txt = self.__driver.find_element_by_xpath(xpath1).text
if txt == self.__no_stock:
#
time.sleep(self.__wait_sec)
self.__log_helper.put(' ' + item_id + ', ')
continue
# path1
xpath2 = "//div[@class='product-list']/div[@class='product']/div[@class='imgDiv']/a"
#
# self.waiting((By.CLASS_NAME, "imgDiv"))
if self.checkIsExistsByPath(xpath2):
self.__driver.find_element_by_xpath(xpath2).click()
time.sleep(self.__wait_sec)
#
if self.checkIsExistsByClass('add-to-cart'):
self.__driver.find_element_by_class_name('add-to-cart').click()
self.__log_helper.put(' , item-id:' + item_id)
break
else:
self.__log_helper.put(' ')
else:
self.__log_helper.put(' , , ')
except BaseException as e:
self.__log_helper.put(e)
def startRun(self):
""" """
try:
self.__running = True
url: str = self.__cfg_info['url']
username = self.__cfg_info['username']
password = self.__cfg_info['password']
item_id = self.__cfg_info['item_id']
if url is None or len(url) == 0 or username is None or len(username) == 0 or password is None or len(
password) == 0 or item_id is None or len(item_id) == 0:
self.__log_helper.put(' , config.cfg , ')
return
if self.__driver is None:
options = webdriver.IeOptions()
options.add_argument('encoding=UTF-8')
options.add_argument('Accept= text / css, * / *')
options.add_argument('Accept - Language= zh - Hans - CN, zh - Hans;q = 0.5')
options.add_argument('Accept - Encoding= gzip, deflate')
options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko')
# 2.
self.__driver = webdriver.Ie(executable_path=self.__work_path + r'\IEDriverServer.exe', options=options)
self.run(url, username, password, item_id)
except BaseException as e:
self.__log_helper.put(' , ')
def run(self, url, username, password, item_id):
""" """
# 3.
self.__driver.get(url)
# 4.
self.__driver.maximize_window()
if self.checkIsExistsByLinkText(' '):
# :
self.login(username, password)
if self.checkIsExistsByPartialLinkText(' '):
# :
self.__log_helper.put(' , ')
self.working(item_id)
else:
self.__log_helper.put(' , ')
def stop(self):
""" """
try:
self.__running = False
# ,
self.close_browser_nicely(self.__driver)
if self.__driver is not None:
self.__driver.quit()
# None,
self.__driver = None
except BaseException as e:
print('Stop Failure')
finally:
self.__driver = None
def close_browser_nicely(self, browser):
try:
browser.execute_script("window.onunload=null; window.onbeforeunload=null")
except Exception as err:
print("Fail to execute_script:'window.onunload=null; window.onbeforeunload=null'")
socket.setdefaulttimeout(10)
try:
browser.quit()
print("Close browser and firefox by calling quit()")
except Exception as err:
print("Fail to quit from browser, error-type:%s, reason:%s" % (type(err), str(err)))
socket.setdefaulttimeout(30)
기타 보조 클래스로그 클래스(LogHelper),코드 는 다음 과 같 습 니 다.
class LogHelper:
""" """
__queue: queue.Queue = None #
__logging: logging.Logger = None #
__running: bool = False #
def __init__(self, log_path):
""" """
self.__queue = queue.Queue(1000)
self.init_log(log_path)
def put(self, value):
""" """
#
self.__logging.info(value)
#
if self.__queue.qsize() < self.__queue.maxsize:
self.__queue.put(value)
def get(self):
""" """
if self.__queue.qsize() > 0:
try:
return self.__queue.get(block=False)
except BaseException as e:
return None
else:
return None
def init_log(self, log_path):
""" """
self.__logging = logging.getLogger()
self.__logging.setLevel(logging.INFO)
#
rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
log_name = log_path + rq + '.log'
logfile = log_name
# if not os.path.exists(logfile):
# #
# open(logfile, mode='r')
fh = logging.FileHandler(logfile, mode='a', encoding='UTF-8')
fh.setLevel(logging.DEBUG) # file log
# , handler
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
fh.setFormatter(formatter)
# , logger handler
self.__logging.addHandler(fh)
def get_running(self):
#
return self.__running
def set_running(self, v: bool):
#
self.__running = v
설정 클래스(ConfigHelper)
class ConfigHelper:
""" """
__config_dir = None
__dic_cfg = {}
def __init__(self, config_dir):
""" """
self.__config_dir = config_dir
def ReadConfigInfo(self):
""" """
parser = ConfigParser()
parser.read(self.__config_dir + r"\config.cfg")
section = parser.sections()[0]
items = parser.items(section)
self.__dic_cfg.clear()
for item in items:
self.__dic_cfg.__setitem__(item[0], item[1])
def getConfigInfo(self):
""" """
if len(self.__dic_cfg) == 0:
self.ReadConfigInfo()
return self.__dic_cfg
스 레 드 클래스(MyThread)
class MyThread(threading.Thread):
""" """
def __init__(self, tid, name, smoking: Smoking, log_helper: LogHelper):
""" """
threading.Thread.__init__(self)
self.threadID = tid
self.name = name
self.smoking = smoking
self.log_helper = log_helper
def run(self):
print(" : " + self.name)
self.log_helper.put(" : " + self.name)
# ,
# lock = threading.Lock()
# lock.acquire()
self.smoking.startRun()
# ,
# lock.release()
print(" : " + self.name)
self.log_helper.put(" : " + self.name)
비고협객 행[당:이 백]조 객 하 염 없 는 호 술,오 구 상설 명.은 안장 이 흰 말 을 비 추 니,마치 유성 처럼 바삭바삭 하 다.
열 걸음 에 한 사람 을 죽 이 고,천 리 를 남기 지 않 는 다.일 을 끝내 고 옷 을 털 고 가서 몸 과 이름 을 깊이 숨기다.
신 릉 을 한가 로 이 지나 가 술 을 마시고 칼 을 벗 고 무릎 을 가로 질 렀 다.주 해 를 구 워 먹고 잔 을 들 어 후 승 을 권 할 것 이다.
세 잔 토 연 노,오악 은 오히려 가볍다.눈 이 어 두 워 지고 귀가 뜨 거 워 지면 의기양양 해진 다.
조 씨 를 구하 고 금 망 치 를 휘 두 르 자 한단 은 먼저 놀 랐 다.천추 2 장사
의협심 이 강하 고 기개 가 있 더 라 도,세상의 영준 함 을 부 끄 럽 게 여기 지 않 는 다.누가 각하,백수 태 현 경 을 읽 을 수 있 겠 습 니까?
파 이 썬 이 Selenium 모 의 브 라 우 저 를 사용 하여 자동 으로 작 동 하 는 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 파 이 썬 모 의 브 라 우 저 자동 작 동 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 십시오.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Python의 None과 NULL의 차이점 상세 정보그래서 대상 = 속성 + 방법 (사실 방법도 하나의 속성, 데이터 속성과 구별되는 호출 가능한 속성 같은 속성과 방법을 가진 대상을 클래스, 즉 Classl로 분류할 수 있다.클래스는 하나의 청사진과 같아서 하나의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.