Python中如何使用scrapy-splash读取iframe下的内容?

用 scrapy-splash 读取的源码, iframe 下的内容没有返回, scrapy-splash 有啥好的解决方法么?除了 selenium 和 phantomjs 。
Python中如何使用scrapy-splash读取iframe下的内容?

1 回复

用scrapy-splash抓取iframe内容,关键在于让Splash先执行页面JavaScript,等iframe加载完再提取数据。核心是scrapy_splash.SplashRequest配合正确的Lua脚本。

下面是个完整示例。假设我们要抓取一个包含iframe的页面,iframe的ID是myframe

import scrapy
from scrapy_splash import SplashRequest

class IframeSpider(scrapy.Spider):
    name = 'iframe_spider'
    
    def start_requests(self):
        # 目标URL
        url = 'http://example.com/page-with-iframe'
        
        # Lua脚本:等待iframe加载并返回其内容
        lua_script = """
        function main(splash)
            splash:go(splash.args.url)
            splash:wait(2)  -- 等待页面初始加载
            
            -- 等待特定iframe加载
            splash:wait_for_resume([[
                function main(splash)
                    local iframe = splash:select('iframe#myframe')
                    if iframe then
                        splash:set_viewport_full()
                        return iframe:info()
                    end
                    return nil
                end
            ]])
            
            -- 切换到iframe上下文
            local iframe = splash:select('iframe#myframe')
            if iframe then
                splash:set_viewport_full()
                local iframe_url = iframe.node.attributes.src
                splash:go(iframe_url)
                splash:wait(1)
            end
            
            return splash:html()
        end
        """
        
        yield SplashRequest(
            url,
            self.parse,
            endpoint='execute',
            args={
                'lua_source': lua_script,
                'timeout': 90
            }
        )
    
    def parse(self, response):
        # 现在response包含的是iframe内的HTML内容
        # 可以像平常一样用XPath或CSS选择器提取数据
        data = response.css('div.content::text').get()
        yield {'data': data}

关键点:

  1. Lua脚本逻辑:先加载主页面,等待iframe出现,然后获取iframe的src地址,让Splash导航到那个地址。
  2. 上下文切换splash:go(iframe_url)让Splash进入iframe内部,后续操作都在iframe的DOM中进行。
  3. 等待机制splash:wait()wait_for_resume确保动态内容加载完成。

如果iframe是跨域的,可能需要额外处理。有些网站用JavaScript动态生成iframe,这时得根据具体情况调整等待条件和选择器。

一句话建议: 让Splash执行JS加载iframe后再跳转进去抓取。

回到顶部