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 관련:
  • Selenium 은 요소 포 지 셔 닝 을 진행 하 는데 주로 ID,Name,ClassName,Css Selector,Partial LinkText,LinkText,XPath,TagName 등 8 가지 방식 이 있 습 니 다.
    Selenium 단일 원소 획득(예:findelement_by_xpath)와 원소 그룹 가 져 오기(예:findelements_by_xpath)두 가지 방식.
    Selenium 요소 가 포 지 셔 닝 되면 요소 에 값 을 부여 하거나 해당 하 는 이벤트 작업 을 할 수 있 습 니 다(예:click).
  • 스 레 드(Thread)관련:
  • 프론트 페이지 의 카드 주인 을 방지 하기 위해 본 고 는 스 레 드 를 사용 하여 배경 작업 을 합 니 다.새로운 스 레 드 를 정의 하려 면 하나의 클래스 를 정의 하고 threading.Thread 를 계승 한 다음 run 방법 을 다시 쓰 면 됩 니 다.
    스 레 드 를 사용 하 는 과정 에서 스 레 드 의 동기 화 를 확보 하기 위해 이 예 는 스 레 드 잠 금 을 사 용 했 습 니 다.예 를 들 어 threading.Lock().
  • 대기 열(queue)관련:
  • 이 예 는 Selenium 이 실행 하 는 과정 정 보 를 열 에 저장 하고 스 레 드 를 통 해 페이지 에 출력 합 니 다.queue 는 기본 적 으로 먼저 나 가 는 방식 입 니 다.
    열 을 put 를 통 해 스 택 을 누 르 고 get 을 통 해 스 택 을 나 갑 니 다.qsize()를 통 해 현재 열 요소 의 개 수 를 가 져 옵 니 다.
  • 로그(logging.Logger)관련:
  • Selenium 실행 중인 로 그 를 저장 하기 위해 로그 모듈 을 사 용 했 습 니 다.Pyhton 자체 모듈 로 추가 설치 가 필요 없습니다.
    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 모 의 브 라 우 저 를 사용 하여 자동 으로 작 동 하 는 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 파 이 썬 모 의 브 라 우 저 자동 작 동 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 십시오.앞으로 많은 응원 바 랍 니 다!

    좋은 웹페이지 즐겨찾기