Contents

【selenium/python】关于用python用selenium4获取网址api接口的事项

关于用python用selenium4获取网址api接口的事项"

缘起

某公司整理自己的营业数据,需要从画面中获取一些列表详情数据。

经过

  1. 安装python环境 pycharm的venv3.10环境简单安装。 selenium 4.11.2

  2. 设置chromedriver 用的是chrome的webdriver,启动之前需要设置。

    options = webdriver.ChromeOptions()
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-gpu')
    options.add_argument('--window-size=1920,1080') #配合无头模式需要设置
    options.add_experimental_option('excludeSwitches', ['enable-automation'])
    options.add_experimental_option('useAutomationExtension', False)
    options.add_argument('--headless') #无头模式,看不到打开的浏览器
    options.set_capability('goog:perfLoggingPrefs', {
        'enableNetwork': True}
    ) # webdriver记录network的log,关键点
    options.set_capability('goog:loggingPrefs', {
        'browser': 'ALL',
        'driver': 'ALL',
        'performance': 'ALL'}
    ) # webdriver记录performance log
    options.set_capability('goog:w3c', False)
    driver = webdriver.Chrome(options=options)
    driver.execute_cdp_cmd(
        'Page.addScriptToEvaluateOnNewDocument',
        {'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'}
    ) # 隐藏自己是webdriver操作浏览器的痕迹
    

    这里主要是要用capability来开启webdriver的api请求记录。 PS:因为是selenium4 cap的写法和3不一样,尝试了半天才弄出来。 里面的key可以参照webdriver的网页

  3. 切换iframe

    driver.switch_to.frame(driver.find_element(by=By.XPATH, value="xxx"))
    

    这个很关键,不然不能正常获取页面上的元素。

  4. 获取api数据

     def log_filter(log_):
     return (
         # is an actual response
         log_["method"] == "Network.responseReceived"
         # and json
         and "json" in log_["params"]["response"]["mimeType"]
    
     ) # 过滤请求数据只拿 返回类型是json的接口
     driver.get_log('performance')
     logs = [json.loads(lr["message"])["message"] for lr in request_log]
     for log in filter(log_filter, logs):
         request_id = log["params"]["requestId"]
         resp_url = log["params"]["response"]["url"]
         if words not in resp_url: #过滤url中关键字
             continue
         req = driver.execute_cdp_cmd("Network.getRequestPostData", {"requestId": request_id})
         print(log["params"]["response"])
         print(f"Caught {resp_url}")
         req = driver.execute_cdp_cmd("Network.getResponseBody", {"requestId": request_id})
         print(req)
         return req
    

    这里重要的是那个request_id通过这个东西利用webdriver api就能获取RequestPostData和ResponseBody。 有了这些数据,就再也不用辛苦的去分析页面上显示和不显示的html控件了。 PS:这个request_id是数字,不是一串英文数字,这里被坑过。

  5. 模拟用户画面操作

     arrow = r.find_element(by=By.CSS_SELECTOR, value='xxx')
     actions = ActionChains(driver)
     actions.move_to_element(arrow)
     actions.pause(1)
     actions.click(arrow)
     actions.pause(5)
     actions.perform()
    

    这里关键是一个action链,最后perform的时候才按顺序执行操作。上面就是移动到特定元素上点击的操作。

结语

末了就没有什么技术难度了,只要没有登录验证码这类东西。