使用 Selenium 获取 ajax (xhr) 数据

记录一下最近一次爬虫的场景和应用,很久没有写了,而且之前的脚本也不好找了。
爬虫场景:需要用户登录系统,输入用户的账号和密码进入系统,进入系统页面后,在chrome浏览器可以查看到,前端页面展示的数据是通过ajax请求后端服务器的数据。
策略:如果不需要登录系统,爬虫很好实现。
我想到的有两种方法,第一种方法手动,比较笨拙,如果数据量不是很多,也够用。
现在很多网站都使用Ajax作为数据接口,这样其实也方便爬虫爬取数据。
chrome浏览器按F12键,调出开发者工具,切换到“Network”,选择筛选XHR资源。当我们点击关注的某些页面,会向后端服务器发送请求返回ajax文件,该ajax文件里面包含我们需要爬取的信息。
点击红色框的下载按钮,保存har文件。下次可以点击旁边的上传按钮,上传har文件。另外,也有一些插件可以辅助har文件浏览。


image1.png

第二种方法是Selenium+chrome driver 实现模拟登陆,使用 Selenium 获取 ajax (xhr) 数据,注意到url是动态生成的,简单的通过requests的post或get方法不易实现。

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os, time, json
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

if __name__ == '__main__':
    # 引入chromedriver
    chrome_options = webdriver.ChromeOptions()
    # chrome_options.add_argument('--headless')
    # chrome_options.add_argument('--no-sandbox')
    # chrome_options.add_argument("--disable-extensions")
    # chrome_options.add_argument("--disable-gpu")
    prefs = {
        'download.default_directory': os.getenv('OS_LOG_PATH')
    }
    chrome_options.add_experimental_option('prefs', prefs)
    # make chrome log requests
    capabilities = DesiredCapabilities.CHROME
    # caps['goog:loggingPrefs']
    capabilities["goog:loggingPrefs"] = {"performance": "ALL"}  # newer: goog:loggingPrefs
    # capabilities['acceptSslCerts'] = True
    #browser = webdriver.Chrome(executable_path=r'/opt/google/chrome/chromedriver', options=chrome_options)
    browser = webdriver.Chrome(executable_path=r'C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe', options=chrome_options,desired_capabilities=capabilities)
    browser.implicitly_wait(3)
    browser.get("https://#########")

    # 输入账号
    browser.implicitly_wait(3)
    username_inputbox = browser.find_elements(By.XPATH, '//*[@id="app"]/section/div[1]/div/div[1]/div/div[2]/form/div[1]/div/div/div/input')[0]
    username_inputbox.click()
    browser.implicitly_wait(3)
    username_inputbox.clear()
    username_inputbox.send_keys("#######")

    # 输入密码
    browser.implicitly_wait(3)
    password_inputbox = browser.find_elements(By.XPATH, '//*[@id="app"]/section/div[1]/div/div[1]/div/div[2]/form/div[2]/div/div/div/input')[0]
    password_inputbox.click()
    browser.implicitly_wait(3)
    password_inputbox.clear()
    password_inputbox.send_keys("#######")

    # 点击登录
    browser.implicitly_wait(3)
    submit_btn = browser.find_elements(By.XPATH, '//*[@id="app"]/section/div[1]/div/div[1]/div/div[2]/form/div[3]/div/button')[0]
    submit_btn.click()
    # 等待5秒
    time.sleep(5)
    #-------------------------------------------------
    base_url = "https://#########"
    browser.get(base_url)

    time.sleep(3)
    # extract requests from logs
    logs_raw = browser.get_log("performance")
    logs = [json.loads(lr["message"])["message"] for lr in logs_raw]

    def log_filter(log_):
        return (
            # is an actual response
                log_["method"] == "Network.responseReceived"
                # and json
                and "json" in log_["params"]["response"]["mimeType"]
        )

    for log in filter(log_filter, logs):
        request_id = log["params"]["requestId"]
        resp_url = log["params"]["response"]["url"]
        print(request_id)
        print(f"Caught {resp_url}")
        json_str = json.dumps(browser.execute_cdp_cmd("Network.getResponseBody", {"requestId": request_id}), indent=4)
        # 创建一个params.json文件
        with open(f'{request_id}.json', 'w') as f:
            f.write(json_str)  # 将json_str写到文件中


    browser.quit()

下载生成每个json文件


image.png

参考链接:
1.https://qiita.com/hatobeam75/items/dbe45324c368eedd4460

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容