Python selenium 获取“开发者工具”→网络→媒体日志

2024-02-27

我正在尝试以编程方式做一些必然涉及获取“开发人员工具”→网络→媒体日志的事情。

我就不告诉你细节了,长话短说,我需要访问数千个页面,如下所示:https://music.163.com/#/song?id=ID, where ID等号后面是一个数字。

如果你打开这样一个页面,就会有一个播放按钮,该按钮会触发一个javascript,加载整个页面中没有引用的音乐文件,并播放该文件。 (注:部分歌曲可能需要中文IP,部分歌曲可能需要VIP账号。)

例如这个页面:https://music.163.com/#/song?id=32477986 https://music.163.com/#/song?id=32477986,它应该看起来像这样:

如果您单击蓝色按钮,则会触发 javascript,并且音乐文件将由 javascript 加载并播放。该音乐文件不会成为网页中的元素,因此无法直接抓取find_element*方法。

但我找到了一种方法来找到音乐文件的地址。

在 Firefox 中,按 F12 打开检查器/“开发人员工具”,单击网络,然后单击媒体。点击蓝色按钮,会出现多个相同文件名的请求,文件名会匹配^[0-9a-f]+\.m4a,并且域可能不同。

像这样:

单击任何记录,您将找到其地址,其中任何一个都可以,如下所示:

我目前正在尝试找出如何以编程方式模拟这个过程。

我用谷歌搜索了这个:,并没有找到我要找的东西,这正是我所期望的。我发布这个链接是为了展示我的研究成果,以及谷歌如何不理解你正在尝试搜索的内容的含义。

无论如何,我偶然发现了这一点:https://www.rkengler.com/how-to-capture-network-traffic-when-scraping-with-selenium-and-python/ https://www.rkengler.com/how-to-capture-network-traffic-when-scraping-with-selenium-and-python/

并用这些进行了测试:

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
capabilities = DesiredCapabilities.CHROME
capabilities["goog:loggingPrefs"] = {'performance': "ALL"}
driver = webdriver.Chrome(desired_capabilities=capabilities)
wait = WebDriverWait(driver, 15)
driver.get('https://music.163.com/#/song?id=32477986')
iframe = driver.find_element_by_xpath('//iframe[@id="g_iframe"]')
driver.switch_to.frame(iframe)
wait.until(EC.visibility_of_element_located((By.XPATH, '//div[2]/div/a[1]')))
play = driver.find_element_by_xpath('//div[2]/div/a[1]')
play.click()
time.sleep(10)
driver.get_log('performance')

它有效,但输出太宽泛,我更喜欢使用 Firefox。

然后我试图找到所有有效的loggingPrefs使用谷歌的选项:,不幸的是,但不出所料,我什么也没找到,除了browser:ALL and driver:ALL.

我找不到任何指定所有可能的开关的文档。

但我想也许我已经找到了一种模式,性能是检查器/开发工具中的一个选项卡,而网络是另一个选项卡。

所以我替换了两次出现的'performance' with 'network'并再次运行代码:

InvalidArgumentException: Message: invalid argument: log type 'network' not found
  (Session info: chrome=89.0.4389.90)

这就是我得到的。

无论如何,这就是我整理的:

import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

options = Options()
options.headless = True
path = (os.environ['APPDATA'] + '\Mozilla\Firefox\Profiles\Selenium').replace('\\', '/')
profile = webdriver.FirefoxProfile(path)
profile.set_preference("media.volume_scale", "0.0")

capabilities = DesiredCapabilities.FIREFOX
capabilities["loggingPrefs"] = {'performance': 'ALL'}

Firefox = webdriver.Firefox(firefox_profile=profile, desired_capabilities=capabilities, options=options)
wait = WebDriverWait(Firefox, 15)
Firefox.get('https://music.163.com/#/song?id=32477986')
iframe = Firefox.find_element_by_xpath('//iframe[@id="g_iframe"]')
Firefox.switch_to.frame(iframe)
wait.until(EC.visibility_of_element_located((By.XPATH, '//div[2]/div/a[1]')))
play = Firefox.find_element_by_xpath('//div[2]/div/a[1]')
play.click()
time.sleep(10)
Firefox.get_log('performance')

这就是它失败的原因:

WebDriverException: Message: HTTP method not allowed

我如何使用 Python selenium 获取网络→媒体日志?我什至无法使日志记录首选项起作用。我发现的所有内容都使用“loggingPrefs”键,正如您所见,它不起作用。我好像依稀记得gecko:loggingPrefs但我无法通过谷歌搜索找到任何东西"gecko:loggingPrefs".

还有这条评论:使用 Selenium 从 Firefox 获取 console.log 输出 https://stackoverflow.com/questions/23231931/getting-console-log-output-from-firefox-with-selenium#comment72831205_23231931提到 driver.get_log('browser') 将不再工作。但尚不清楚它是否仅适用于browser或所有日志。

如何获取 Firefox 检查器日志以及如何将其范围缩小到网络→媒体选项卡?

我真的很抱歉,如果我没有表现出足够的研究努力,我到底如何在不使用谷歌的情况下在线研究一些东西呢?难道您从自己使用 Google 的经验中还不够了解吗?Google 永远不会理解您搜索词的含义,它只会查找包含关键字的文档,其中关键字随机散布在文档中,并且结果甚至不必包含所有内容关键词!

谷歌确实是一个糟糕的研究工具,我真的没有什么比谷歌更好的了。因此,如果这还不够,那么我不知道有什么可以算作足够的研究工作。

那么如何使用 Python 3.9.5 selenium 在 Firefox 中获取检查器→网络→媒体日志?


谷歌引导我来到这里,坦率地说,现场搜索引擎甚至比谷歌还要糟糕。我找不到我正在寻找的答案,这正是我在这里提出问题的原因。


经过更多研究,我终于发现了一些东西:https://stackoverflow.com/a/65538568/15290516 https://stackoverflow.com/a/65538568/15290516

这个答案让我离我的目标又近了一步,但我对 javascript 一无所知,测试返回:

JavascriptException: Message: Cyclic object value

但它确实指出了正确的方向,解决方案应该包括.execute_script()为了完成工作,但我不知道命令应该是什么,我尝试谷歌搜索:,亲自看看它返回什么。


嗯,我设法用 Chrome 获取性能日志并将其重定向到一个文本文件,我将其上传到谷歌云端硬盘 https://drive.google.com/file/d/1ml2GXi5wuHedROWLHsoJO7jacC7DJnTI/view?usp=sharing.

我已经在文件中找到了地址(Notepad++搜索.m4a),但我不知道如何以编程方式将结果过滤到与音乐文件相关的请求。

我想,现在我会被 Chrome 和性能日志困住。

但我真的不知道如何过滤请求以仅获取相关请求。那怎么办呢?


最后我自己完成了这件事,没有任何人的帮助。

技巧很简单,一旦你知道该怎么做,实现它并不难。

响应是 json 格式,所以我们需要json module.

json的结构各不相同,但第一级键是固定的,总是三个键:level, message, timestamp.

我们需要messagekey,它的value是一个封装在字符串中的json对象,所以我们需要json.loads打开它的包装。

这些打包的json对象的结构变化很大,但总有一个message钥匙和一个method里面的钥匙message key.

在这里,我们尝试抓取收到的媒体文件地址,长话短说,messagemessagemethod键应该等于'Network.responseReceived'.

If messagemessagemethod键等于'Network.responseReceived',那么总会有一个messagemessageparamsresponsemimeType key.

该键存储资源的文件类型,我就不告诉你细节了,我知道.mp4代表Motion Picture Expert Group-4是一种视频格式,但这里的媒体类型应该是'audio/mp4'.

如果满足所有有关条件,则媒体文件的地址的值为messagemessageparamsresponseurl key.

这是最终的代码:

import json
import os
import random
import sys
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

path = (os.environ['LOCALAPPDATA'] + '\\Google\\Chrome\\User Data')

options = webdriver.ChromeOptions()
options.add_argument('--disable-gpu')
options.add_argument('--headless')
options.add_argument('--log-level=3')
options.add_argument('--mute-audio')
options.add_argument(f'--user-data-dir={path}')

capabilities = DesiredCapabilities.CHROME
capabilities["goog:loggingPrefs"] = {'performance': 'ALL'}

Chrome = webdriver.Chrome(options=options, desired_capabilities=capabilities)
wait = WebDriverWait(Chrome, 5)

def getlink(addr):
    Chrome.get(addr)
    iframe = Chrome.find_element_by_xpath('//iframe[@id="g_iframe"]')
    Chrome.switch_to.frame(iframe)
    wait.until(EC.visibility_of_element_located((By.XPATH, '//div[2]/div/a[1]')))
    play = Chrome.find_element_by_xpath('//div[2]/div/a[1]')
    play.click()
    time.sleep(5)
    logs = Chrome.get_log('performance')
    addresses = []
    for i in logs:
        log = json.loads(i['message'])
        if log['message']['method'] == 'Network.responseReceived':
            if log['message']['params']['response']['mimeType'] == 'audio/mp4':
                addresses.append(log['message']['params']['response']['url'])
    check = set([i.split('/')[-1] for i in addresses])
    if len(check) == 1:
        return random.choice(addresses)

if __name__ == '__main__':
    print(getlink(sys.argv[1]))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python selenium 获取“开发者工具”→网络→媒体日志 的相关文章

  • 如何使用固定的 pandas 数据框进行动态 matplotlib 绘图?

    我有一个名为的数据框benchmark returns and strategy returns 两者具有相同的时间跨度 我想找到一种方法以漂亮的动画风格绘制数据点 以便它显示逐渐加载的所有点 我知道有一个matplotlib animat
  • 如何生成给定范围内的回文数列表?

    假设范围是 1 X 120 这是我尝试过的 gt gt gt def isPalindrome s check if a number is a Palindrome s str s return s s 1 gt gt gt def ge
  • 如何打印没有类型的defaultdict变量?

    在下面的代码中 from collections import defaultdict confusion proba dict defaultdict float for i in xrange 10 confusion proba di
  • pandas 替换多个值

    以下是示例数据框 gt gt gt df pd DataFrame a 1 1 1 2 2 b 11 22 33 44 55 gt gt gt df a b 0 1 11 1 1 22 2 1 33 3 2 44 4 3 55 现在我想根据
  • 如何在Windows上模拟socket.socketpair

    标准Python函数套接字 套接字对 https docs python org 3 library socket html socket socketpair不幸的是 它在 Windows 上不可用 从 Python 3 4 1 开始 我
  • Spark的distinct()函数是否仅对每个分区中的不同元组进行洗牌

    据我了解 distinct 哈希分区 RDD 来识别唯一键 但它是否针对仅移动每个分区的不同元组进行了优化 想象一个具有以下分区的 RDD 1 2 2 1 4 2 2 1 3 3 5 4 5 5 5 在此 RDD 上的不同键上 所有重复键
  • 为 pandas 数据透视表中的每个值列定义 aggfunc

    试图生成具有多个 值 列的数据透视表 我知道我可以使用 aggfunc 按照我想要的方式聚合值 但是如果我不想对两列求和或求平均值 而是想要一列的总和 同时求另一列的平均值 该怎么办 那么使用 pandas 可以做到这一点吗 df pd D
  • __del__ 真的是析构函数吗?

    我主要用 C 做事情 其中 析构函数方法实际上是为了销毁所获取的资源 最近我开始使用python 这真的很有趣而且很棒 我开始了解到它有像java一样的GC 因此 没有过分强调对象所有权 构造和销毁 据我所知 init 方法对我来说在 py
  • 从列表中的数据框列中搜索部分字符串匹配 - Pandas - Python

    我有一个清单 things A1 B2 C3 我有一个 pandas 数据框 其中有一列包含用分号分隔的值 某些行将包含与上面列表中的一项的匹配 它不会是完美的匹配 因为它在其中包含字符串的其他部分 该列 例如 该列中的一行可能有 哇 这里
  • python pandas 中的双端队列

    我正在使用Python的deque 实现一个简单的循环缓冲区 from collections import deque import numpy as np test sequence np array range 100 2 resha
  • Python:字符串不会转换为浮点数[重复]

    这个问题在这里已经有答案了 我几个小时前写了这个程序 while True print What would you like me to double line raw input gt if line done break else f
  • 循环中断打破tqdm

    下面的简单代码使用tqdm https github com tqdm tqdm在循环迭代时显示进度条 import tqdm for f in tqdm tqdm range 100000000 if f gt 100000000 4 b
  • Python - 在窗口最小化或隐藏时使用 pywinauto 控制窗口

    我正在尝试做的事情 我正在尝试使用 pywinauto 在 python 中创建一个脚本 以在后台自动安装 notepad 隐藏或最小化 notepad 只是一个示例 因为我将编辑它以与其他软件一起使用 Problem 问题是我想在安装程序
  • 通过数据框与函数进行交互

    如果我有这样的日期框架 氮 EG 00 04 NEG 04 08 NEG 08 12 NEG 12 16 NEG 16 20 NEG 20 24 datum von 2017 10 12 21 69 15 36 0 87 1 42 0 76
  • 在Python中重置生成器对象

    我有一个由多个yield 返回的生成器对象 准备调用该生成器是相当耗时的操作 这就是为什么我想多次重复使用生成器 y FunctionWithYield for x in y print x here must be something t
  • 在 Pandas DataFrame Python 中添加新列[重复]

    这个问题在这里已经有答案了 例如 我在 Pandas 中有数据框 Col1 Col2 A 1 B 2 C 3 现在 如果我想再添加一个名为 Col3 的列 并且该值基于 Col2 式中 如果Col2 gt 1 则Col3为0 否则为1 所以
  • 对输入求 Keras 模型的导数返回全零

    所以我有一个 Keras 模型 我想将模型的梯度应用于其输入 这就是我所做的 import tensorflow as tf from keras models import Sequential from keras layers imp
  • 如何使用google colab在jupyter笔记本中显示GIF?

    我正在使用 google colab 想嵌入一个 gif 有谁知道如何做到这一点 我正在使用下面的代码 它并没有在笔记本中为 gif 制作动画 我希望笔记本是交互式的 这样人们就可以看到代码的动画效果 而无需运行它 我发现很多方法在 Goo
  • 使用基于正则表达式的部分匹配来选择 Pandas 数据帧的子数据帧

    我有一个 Pandas 数据框 它有两列 一列 进程参数 列 包含字符串 另一列 值 列 包含相应的浮点值 我需要过滤出部分匹配列 过程参数 中的一组键的子数据帧 并提取与这些键匹配的数据帧的两列 df pd DataFrame Proce
  • 改变字典的哈希函数

    按照此question https stackoverflow com questions 37100390 towards understanding dictionaries 我们知道两个不同的字典 dict 1 and dict 2例

随机推荐