You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从iframe中提取MP4视频URL?(Python/Rust实现)

从IFrame中提取MP4视频URL的解决方案

问题描述

需要用Python或Rust(不限库)从IFrame中提取MP4视频URL,示例IFrame如下:

<iframe src="https://spinning.allohalive.com/?kp=1332827&token=b51bdfc8af17dee996d3eae53726df" />

已尝试Bs4、Selenium、Scrapy等工具,耗时两周仍未成功,现有用于解析目标网站IFrame的Scrapy代码如下:

import scrapy

from cimber.models.website import Website


class KinokradSpider(scrapy.Spider):
    name = "kinokrad"
    start_urls = [Website.Kinokrad.value]

    def __init__(self):
        self.pages_count = 1

    def parse(self, response):
        pages_count = self.get_pages_count(response)

        if self.pages_count <= pages_count:
            for film in response.css("div.shorposterbox"):
                film_url = film.css("div.postertitle").css("a").attrib["href"]
                yield scrapy.Request(film_url, callback=self.parse_film)

            next_page = f"{Website.Kinokrad.value}/page/{self.pages_count}"
            if next_page is not None:
                yield response.follow(next_page, callback=self.parse)

            self.pages_count += 1

    def parse_film(self, response):
        name = response.css("div.fallsttitle").css("h1::text").get().strip()
        players = []

        for player in  response.css("iframe::attr(src)").extract():
            players.append(player)

        yield {
            "name": name,
            "players": players
        }

    def get_pages_count(self, response) -> int:
        links = response.css("div.navcent").css("a")
        last_link = links[len(links) - 1].attrib["href"]

        return int(last_link.split("/page/")[1].replace("/", "").strip())

解决方案思路

1. 核心问题分析

IFrame指向的页面大多通过JavaScript动态加载视频资源,静态爬取HTML无法直接拿到MP4 URL,必须处理动态渲染的内容:要么解析页面中的JS代码提取视频地址,要么模拟浏览器执行JS,等待视频加载后获取真实URL。

2. Python实现方案(Scrapy + Playwright)

Playwright能模拟真实浏览器环境,执行页面JS并捕获动态加载的资源,适合解决这类问题。

步骤1:安装依赖

pip install scrapy playwright
playwright install chromium

步骤2:修改爬虫代码

在parse_film方法中,对每个IFrame地址发起浏览器请求,提取视频URL:

import scrapy
from playwright.sync_api import sync_playwright
from cimber.models.website import Website


class KinokradSpider(scrapy.Spider):
    name = "kinokrad"
    start_urls = [Website.Kinokrad.value]

    def __init__(self):
        self.pages_count = 1

    def parse(self, response):
        pages_count = self.get_pages_count(response)

        if self.pages_count <= pages_count:
            for film in response.css("div.shorposterbox"):
                film_url = film.css("div.postertitle").css("a").attrib["href"]
                yield scrapy.Request(film_url, callback=self.parse_film)

            next_page = f"{Website.Kinokrad.value}/page/{self.pages_count}"
            if next_page is not None:
                yield response.follow(next_page, callback=self.parse)

            self.pages_count += 1

    def parse_film(self, response):
        name = response.css("div.fallsttitle").css("h1::text").get().strip()
        players = response.css("iframe::attr(src)").extract()
        video_urls = []

        with sync_playwright() as p:
            browser = p.chromium.launch(headless=True)
            for player_url in players:
                page = browser.new_page(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36")
                # 等待页面加载完成,网络请求稳定
                page.goto(player_url, wait_until="networkidle")
                # 优先查找video标签的src属性,可根据实际页面调整选择器
                video_element = page.query_selector("video")
                if video_element:
                    video_src = video_element.get_attribute("src")
                    if video_src and video_src.endswith(".mp4"):
                        video_urls.append(video_src)
                # 若video标签无src,尝试解析页面中的JS变量(示例逻辑,需根据实际页面调整)
                else:
                    video_data = page.evaluate("""() => {
                        // 假设页面中有window.videoInfo这样的变量存储视频地址
                        return window.videoInfo?.src || null
                    }""")
                    if video_data:
                        video_urls.append(video_data)
                page.close()
            browser.close()

        yield {
            "name": name,
            "players": players,
            "video_urls": video_urls
        }

    def get_pages_count(self, response) -> int:
        links = response.css("div.navcent").css("a")
        last_link = links[len(links) - 1].attrib["href"]

        return int(last_link.split("/page/")[1].replace("/", "").strip())

3. 关键注意事项

  • 目标网站可能有反爬机制,需添加真实的User-Agent,设置请求间隔,避免被封禁
  • 不同视频页面的DOM结构或JS逻辑不同,需通过浏览器开发者工具分析:查看视频元素的属性、查找存储视频URL的JS变量,或追踪网络请求中MP4文件的地址
  • 若遇到加密的视频URL,可能需要分析页面的解密逻辑,模拟生成有效地址

内容的提问来源于stack exchange,提问作者Александр Прокопенко

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 16:30:49