Skip to main content
 首页 » 编程设计

python之使用带有 scrapy 和 splash 的 javascript 递归抓取同一页面

2024年08月21日37落叶无声

我正在抓取一个具有 javascript 的站点以转到下一页。我正在使用 splash 在第一页上执行我的 javascript 代码。但是我能够转到第二页。但我无法转到第 3、4、5... 页。抓取仅在一页后停止。

我正在抓取的链接: http://59.180.234.21:8788/user/viewallrecord.aspx

代码:

import scrapy 
from scrapy_splash import SplashRequest 
from time import sleep 
 
 
class MSEDCLSpider(scrapy.Spider): 
    name = "msedcl_spider" 
    scope_path = 'body > table:nth-child(11) tr > td.content_area > table:nth-child(4) tr:not(:first-child)' 
    ref_no_path = "td:nth-child(1) ::text" 
    title_path = "td:nth-child(2) ::text" 
    end_date_path = "td:nth-child(5) ::text" 
    fee_path = "td:nth-child(6) ::text" 
    start_urls = ["http://59.180.234.21:8788/user/viewallrecord.aspx"] 
 
    lua_src = """function main(splash) 
        local url = splash.args.url 
        splash:go(url) 
        splash:wait(2.0) 
        splash:runjs("document.querySelectorAll('#lnkNext')[0].click()") 
        splash:wait(4.0) 
        return { 
            splash:html(), 
        } 
        end 
        """ 
 
    def start_requests(self): 
        for url in self.start_urls: 
            yield SplashRequest( 
                url, 
                self.parse, 
                endpoint='execute', 
                method='POST', 
                dont_filter=True, 
                args={ 
                    'wait': 1.0, 
                    'lua_source': self.lua_src, 
                }, 
            ) 
 
 
    def parse(self, response): 
        print response.status 
        scopes = response.css('#page-info').extract()[0] 
        print(response.url) 
        print(scopes) 

我是 scrapy 和 splash 的新手。请温柔点谢谢

请您参考如下方法:

我可以看到两个问题:

  1. 您没有提出这些请求。在 start_requests 中发出了一个请求,响应在 self.parse 方法中被解析,但是对第三页和其他页面的请求永远不会发送。为此,您需要从 .parse 方法发送一些请求。

  2. 如果您修复 (1),那么您可能会面临下一个问题:Splash 不会在请求之间保持页面状态。将每个请求视为打开一个新的隐私模式浏览器窗口并执行一些操作;这是设计使然。但是这个网站的问题是 URL 不会在页面之间改变,所以你不能只是开始,例如从第 3 页开始,然后单击“下一步”页面。

但我认为有一些方法可以解决 (2)。也许您可以在单击后获取页面 html,然后使用 splash:set_content 将其加载到浏览器中;你也可以保留 cookie——在 scrapy-splash README 中有一个例子;尽管该网站似乎并不依赖 cookie 进行分页。

另一种方法是编写一个脚本来加载所有页面,而不仅仅是下一页,然后将所有页面的内容返回给客户端。像这样的东西(未经测试):

function main(splash)  
    splash:go(splash.args.url) 
    local pages = {splash:html()} 
    for i = 2,100 do              
        splash:runjs("document.querySelectorAll('#lnkNext')[0].click()")             
        splash:wait(4) 
        pages[i] = splash:html() 
    end 
    return pages 
end 

为此,您需要更大的超时值;您可能还必须使用更大的 --max-timeout 选项启动 Splash。