python - splash lua脚本做多次点击访问

标签 python scrapy scrapy-splash splash-js-render

我正在尝试抓取 Google Scholar search results并获取与搜索匹配的每个结果的所有 BiBTeX 格式。现在我有一个带有 Splash 的 Scrapy 爬虫。我有一个 lua 脚本,它将单击“引用”链接并在获取引文的 BibTeX 格式的 href 之前加载模式窗口。但是看到有多个搜索结果,因此有多个“引用”链接,我需要单击它们并加载各个 BibTeX 页面。

这是我所拥有的:

import scrapy
from scrapy_splash import SplashRequest


class CiteSpider(scrapy.Spider):
    name = "cite"
    allowed_domains = ["scholar.google.com", "scholar.google.ae"]
    start_urls = [
        'https://scholar.google.ae/scholar?q="thermodynamics"&hl=en'
    ]

    script = """
        function main(splash)
          local url = splash.args.url
          assert(splash:go(url))
          assert(splash:wait(0.5))
          splash:runjs('document.querySelectorAll("a.gs_nph[aria-controls=gs_cit]")[0].click()')
          splash:wait(3)
          local href = splash:evaljs('document.querySelectorAll(".gs_citi")[0].href')
          assert(splash:go(href))
          return {
            html = splash:html(),
            png = splash:png(),
            href=href,
          }
        end
        """

    def parse(self, response):
        yield SplashRequest(self.start_urls[0], self.parse_bib,
                            endpoint="execute",
                            args={"lua_source": self.script})

    def parse_bib(self, response):
        filename = response.url.split("/")[-2] + '.html'
        with open(filename, 'wb') as f:
            f.write(response.css("body > pre::text").extract()[0])

我想我应该在执行 querySelectorAll 调用时将“Cite”链接的索引传递到 lua 脚本中,但我似乎找不到将另一个变量传递到 lua 脚本中的方法功能。此外,我假设在获得 BibTeX 后我将不得不做一些肮脏的 javascript history.back() 以返回到原始结果页面,但我觉得有一种更优雅的方式来处理这个问题。

最佳答案

好吧,我想出了一个可行的解决方案。首先,我们需要 Lua 脚本是可变的,所以我们将其设为函数:

def script(n):
    _script = """
        function main(splash)
          local url = splash.args.url
          local href = ""
          assert(splash:go(url))
          assert(splash:wait(0.5))
          splash:runjs('document.querySelectorAll("a.gs_nph[aria-controls=gs_cit]")[{}].click()')
          splash:wait(3)
          href = splash:evaljs('document.querySelectorAll("a.gs_citi")[0].href')
          assert(splash:go(href))
          return {}
        end
        """.format(n, "{html=splash:html(),png=splash:png(), href=href,}")
    return _script

然后我必须修改 parse 函数,以便它单击页面上的所有“引用”链接。这样做的方法是遍历页面上所有匹配的“引用”链接,然后分别单击每个链接。我让 Lua 脚本再次加载页面(这很脏但我想不出任何其他方式)并单击查询的“引用”链接的索引。此外,它还必须发出重复请求,因此存在 dont_filter=True 的原因:

def parse(self, response):
        n = len(response.css("a.gs_nph[aria-controls=gs_cit]").extract())
        for i in range(n):
            yield SplashRequest(response.url, self.parse_bib,
                                endpoint="execute",
                                args={"lua_source": script(i)},
                                dont_filter=True)

希望这对您有所帮助。

关于python - splash lua脚本做多次点击访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38043672/

相关文章:

python - beautifulsoup 无法识别 lxml

python - 在类 __exit__ 或 __del__ 方法中关闭文件?

python - 使用 Scrapy-Splash 的代理服务器

python - 检查列表中的元素是否存在于python中的多个列表中

Python OpenCV SVM 实现

python - 尽管继承自 CrawlSpider,但 Scrapy NotImplemented 解析错误

python - 如何使用 scrapy 将多个页面的数据收集到单个数据结构中

python - 谷歌搜索

python - 单击 Scrapy-Splash 中的按钮

scrapy - CrawlSpider with Splash 在第一个 URL 后卡住