尝试在 python 中阅读带有 scrapy splash 的分页 asp 页面

Trying to read paginated asp pages with scrapy splash in python

我正在尝试使用 scrapy 和 splash 从特定网站的员工页面检索员工、职位和电子邮件。 https://www.kennedaleisd.net/Page/3884。我在 docker 中使用 splash,因为电子邮件隐藏在动态 javascript 代码之后。

蜘蛛在工作人员的第一页上工作,但我似乎无法让它在第二或第三页上工作。我打开了开发人员工具并复制了当您单击其中一个分页链接时发送的请求,然后尝试在蜘蛛中复制该请求。我似乎遇到的问题是,对该请求的响应只是 returns 整个页面的代码子集(只是该页面的工作人员),而不是随附的 javascript 之类的所有内容.因此,当它被传递到 splash 时,它没有必要的脚本来创建动态代码。我还注意到请求似乎有一个 RedirectTo 的 cookie 条目,它返回到父页面。我曾尝试在请求中包含该 cookie 或将 cookie 从第一个请求传递到分页页面,但它似乎没有用。我还在启动请求中尝试了一些 lua 脚本,但这似乎也没有得到我想要的东西。下面我已经包括了我现在拥有的蜘蛛。

我不确定是否有某种方法可以在后续请求中重新使用 javascript 或以某种方式重新使用 cookie 的用户以获取所需的其余代码。任何帮助,将不胜感激。我意识到分页可能不是循环浏览页面的正确方法,但我想一旦我弄清楚了数据的读取方式,我就可以解决这个问题。

import scrapy
from scrapy_splash import SplashRequest


class TestSpider(scrapy.Spider):
    name = 'TestSpider'
    start_urls = ['https://www.kennedaleisd.net/Page/3884']

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url, self.parse, meta={
                'splash': {
                    'endpoint': 'render.html',
                    'args': {'wait': 0.5}
                }
            })

    def parse(self, response):

        for item in response.css('div.staff'):

            name = item.css('li.staffname::text').get()
            title = item.css('li.staffjob::attr(data-value)').get()
            email = item.css('li.staffemail a::attr(href)').get()
            staffURL = response.request.url

            yield {
                'name': name,
                'title': title,
                'email': email,
                'staffURL': staffURL
            }

        if response.css('a.ui-page-number-current-span::text').get() == '1':
            pagination_results = response.css(
                'li.ui-page-number a:not([class^="ui-page-number-current-span"])::text').getall()

            base_url = 'https://www.kennedaleisd.net//cms/UserControls/ModuleView/ModuleViewRendererWrapper.aspx?DomainID=2042&PageID=3884&ModuleInstanceID=6755&PageModuleInstanceID=7911&Tag=&PageNumber='
            # backend_url = '&RenderLoc=0&FromRenderLoc=0&IsMoreExpandedView=false&EnableQuirksMode=0&Filter=&ScreenWidth=922&ViewID=00000000-0000-0000-0000-000000000000&_=1584114139549'

            for i in pagination_results:

                next_page = base_url + str(i)  # + backend_url

                yield response.follow(next_page, callback=self.parse, meta={
                    'splash': {
                        'endpoint': 'render.html',
                        'args': {'wait': 3}
                    }
                })

好吧,经过一番修改后,我想出了如何使用我一直在玩弄的 lua 脚本来处理这个问题。如果有更正式的东西而不是使用脚本,我仍然更喜欢不同的方法。

import scrapy
from scrapy_splash import SplashRequest

script_frontend = """
function main(splash)
  splash:init_cookies(splash.args.cookies)
  assert(splash:go{
    splash.args.url,
    headers=splash.args.headers,
    http_method=splash.args.http_method,
    body=splash.args.body,
    })
  assert(splash:wait(3))

  assert(splash:select('#ui-paging-container > ul > li:nth-child("""

script_backend = """) > a'):mouse_click())
  assert(splash:wait(3))

  local entries = splash:history()
  local last_response = entries[#entries].response
  return {
    url = splash:url(),
    headers = last_response.headers,
    http_status = last_response.status,
    cookies = splash:get_cookies(),
    html = splash:html(),
  }
end
"""

class TestSpider(scrapy.Spider):
    name = 'TestSpider'
    start_urls = ['https://www.kennedaleisd.net/Page/3884']

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url, self.parse, meta={
                'splash': {
                    'endpoint': 'render.html',
                    'args': {'wait': 0.5}
                }
            })

    def parse(self, response):

        for item in response.css('div.staff'):

            name = item.css('li.staffname::text').get()
            title = item.css('li.staffjob::attr(data-value)').get()
            email = item.css('li.staffemail a::attr(href)').get()
            staffURL = response.request.url

            yield {
                'name': name,
                'title': title,
                'email': email,
                'staffURL': staffURL
            }

        if response.css('a.ui-page-number-current-span::text').get() == '1':
            pagination_results = response.css(
                'li.ui-page-number a:not([class^="ui-page-number-current-span"])::text').getall()

            for i in pagination_results:

                script = script_frontend + str(i) + script_backend

                yield SplashRequest(self.start_urls[0], self.parse,
                                    endpoint='execute',
                                    cache_args=['lua_source'],
                                    args={'lua_source': script},
                                    headers={'X-My-Header': 'value'},
                                    session_id='foo'
                                    )