Splash lua 脚本做多次点击和访问
Splash lua script to do multiple clicks and visits
我正在尝试抓取 Google Scholar search results 并获取与搜索匹配的每个结果的所有 BiBTeX 格式。现在我有一个带有 Splash 的 Scrapy 爬虫。我有一个 lua 脚本,它将单击 "Cite" link 并在获取引文的 BibTeX 格式的 href
之前加载模态 window。但是看到有多个搜索结果,因此有多个 "Cite" links,我需要单击它们并加载各个 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" link 的索引传递到 lua 脚本中,但我似乎无法找到一种方法将另一个变量传递给函数。此外,我假设在获得 BibTeX 后,我将不得不做一些肮脏的 javascript history.back()
到 return 回到原始结果页面,但我觉得有一种更优雅的方式来处理这个问题。
好吧,我想出了一个可行的解决方案。首先,我们需要 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
函数,以便它点击页面上的所有 "Cite" link。这样做的方法是遍历页面上所有匹配的 "Cite" link 并分别单击每个。我让 Lua 脚本再次加载页面(这很脏但我想不出任何其他方式)并单击查询的索引 "Cite" link。它还必须发出重复请求,因此 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)
希望对您有所帮助。
我正在尝试抓取 Google Scholar search results 并获取与搜索匹配的每个结果的所有 BiBTeX 格式。现在我有一个带有 Splash 的 Scrapy 爬虫。我有一个 lua 脚本,它将单击 "Cite" link 并在获取引文的 BibTeX 格式的 href
之前加载模态 window。但是看到有多个搜索结果,因此有多个 "Cite" links,我需要单击它们并加载各个 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" link 的索引传递到 lua 脚本中,但我似乎无法找到一种方法将另一个变量传递给函数。此外,我假设在获得 BibTeX 后,我将不得不做一些肮脏的 javascript history.back()
到 return 回到原始结果页面,但我觉得有一种更优雅的方式来处理这个问题。
好吧,我想出了一个可行的解决方案。首先,我们需要 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
函数,以便它点击页面上的所有 "Cite" link。这样做的方法是遍历页面上所有匹配的 "Cite" link 并分别单击每个。我让 Lua 脚本再次加载页面(这很脏但我想不出任何其他方式)并单击查询的索引 "Cite" link。它还必须发出重复请求,因此 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)
希望对您有所帮助。