Python 使用Splash将Scrapy POST发布到Javascript生成的表单

Python 使用Splash将Scrapy POST发布到Javascript生成的表单,python,web-scraping,scrapy,splash-screen,scrapyjs,Python,Web Scraping,Scrapy,Splash Screen,Scrapyjs,我有下面的蜘蛛,它几乎只是应该发布到一个表单上。 但我似乎无法让它发挥作用。当我通过Scrapy做这件事时,反应从来没有表现出来。 谁能告诉我这件事哪里出了问题 这是我的蜘蛛代码: # -*- coding: utf-8 -*- from __future__ import unicode_literals import scrapy from scrapy.http import FormRequest from scrapy.shell import inspect_response c

我有下面的蜘蛛,它几乎只是应该发布到一个表单上。 但我似乎无法让它发挥作用。当我通过Scrapy做这件事时,反应从来没有表现出来。 谁能告诉我这件事哪里出了问题

这是我的蜘蛛代码:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import scrapy
from scrapy.http import FormRequest
from scrapy.shell import inspect_response


class RajasthanSpider(scrapy.Spider):
    name = "rajasthan"
    allowed_domains = ["rajtax.gov.in"]
    start_urls = (
        'http://www.rajtax.gov.in/',
    )

    def parse(self, response):
        return FormRequest.from_response(
            response,
            formname='rightMenuForm',
            formdata={'dispatch': 'dealerSearch'},
            callback=self.dealer_search_page)

    def dealer_search_page(self, response):

        yield FormRequest.from_response(
            response,
            formname='dealerSearchForm',
            formdata={
                "zone": "select",
                "dealertype": "VAT",
                "dealerSearchBy": "dealername",
                "name": "ana"
            }, callback=self.process)

    def process(self, response):
        inspect_response(response, self)
我得到的答复如下:

我应该得到这样的结果:

当我用Splash替换我的
经销商搜索页面()
时,如下所示:

def dealer_search_page(self, response):

    yield FormRequest.from_response(
        response,
        formname='dealerSearchForm',
        formdata={
            "zone": "select",
            "dealertype": "VAT",
            "dealerSearchBy": "dealername",
            "name": "ana"
        },
        callback=self.process,
        meta={
            'splash': {
                'endpoint': 'render.html',
                'args': {'wait': 0.5}
            }
        })
我得到以下警告:

2016-03-14 15:01:29 [scrapy] WARNING: Currently only GET requests are supported by SplashMiddleware; <POST http://rajtax.gov.in:80/vatweb/dealerSearch.do> will be handled without Splash
2016-03-14 15:01:29[scrapy]警告:目前Splash中间件只支持GET请求;将在无飞溅的情况下进行处理
程序在到达my
process()
函数中的my
inspect\u response()
之前退出

错误表明Splash还不支持
POST
Splash
是否适用于此用例,或者我是否应该使用
Selenium

您可以使用。下面是一个完整的工作示例,我们使用与您的剪贴代码中相同的搜索参数提交表单,并在控制台上打印结果:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


driver = webdriver.Firefox()
driver.get("http://www.rajtax.gov.in/")

# accept the alert
driver.switch_to.alert.accept()

# open "Search for Dealers"
wait = WebDriverWait(driver, 10)
search_for_dealers = wait.until(EC.visibility_of_element_located((By.PARTIAL_LINK_TEXT, "Search for Dealers")))
search_for_dealers.click()

# set search parameters
dealer_type = Select(driver.find_element_by_name("dealertype"))
dealer_type.select_by_visible_text("VAT")

search_by = Select(driver.find_element_by_name("dealerSearchBy"))
search_by.select_by_visible_text("Dealer Name")

search_criteria = driver.find_element_by_name("name")
search_criteria.send_keys("ana")

# search
driver.find_element_by_css_selector("table.vattabl input.submit").click()

# wait for and print results
table = wait.until(EC.visibility_of_element_located((By.XPATH, "//table[@class='pagebody']/following-sibling::table")))

for row in table.find_elements_by_css_selector("tr")[1:]:  # skipping header row
    print(row.find_elements_by_tag_name("td")[1].text)
打印搜索结果表中的TIN编号:

08502557052
08451314461
...
08734200736
请注意,使用selenium自动化的浏览器可以是无头浏览器,也可以是虚拟显示器上的常规浏览器


回答初始问题(编辑前):

我在经销商搜索页面上看到的是——表单及其字段是由浏览器中执行的一系列JavaScript脚本构成的。Scrapy无法执行JS,您需要帮助它完成此部分。我敢肯定,在这种情况下就足够了,您不需要进入浏览器自动化。下面是一个将Scrapy与Splash一起使用的工作示例:

你可以通过以下方式接近它。下面是一个完整的工作示例,我们使用与您的剪贴代码中相同的搜索参数提交表单,并在控制台上打印结果:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


driver = webdriver.Firefox()
driver.get("http://www.rajtax.gov.in/")

# accept the alert
driver.switch_to.alert.accept()

# open "Search for Dealers"
wait = WebDriverWait(driver, 10)
search_for_dealers = wait.until(EC.visibility_of_element_located((By.PARTIAL_LINK_TEXT, "Search for Dealers")))
search_for_dealers.click()

# set search parameters
dealer_type = Select(driver.find_element_by_name("dealertype"))
dealer_type.select_by_visible_text("VAT")

search_by = Select(driver.find_element_by_name("dealerSearchBy"))
search_by.select_by_visible_text("Dealer Name")

search_criteria = driver.find_element_by_name("name")
search_criteria.send_keys("ana")

# search
driver.find_element_by_css_selector("table.vattabl input.submit").click()

# wait for and print results
table = wait.until(EC.visibility_of_element_located((By.XPATH, "//table[@class='pagebody']/following-sibling::table")))

for row in table.find_elements_by_css_selector("tr")[1:]:  # skipping header row
    print(row.find_elements_by_tag_name("td")[1].text)
打印搜索结果表中的TIN编号:

08502557052
08451314461
...
08734200736
请注意,使用selenium自动化的浏览器可以是无头浏览器,也可以是虚拟显示器上的常规浏览器


回答初始问题(编辑前):

我在经销商搜索页面上看到的是——表单及其字段是由浏览器中执行的一系列JavaScript脚本构成的。Scrapy无法执行JS,您需要帮助它完成此部分。我敢肯定,在这种情况下就足够了,您不需要进入浏览器自动化。下面是一个将Scrapy与Splash一起使用的工作示例:


    • 现在Splash支持POST请求。请尝试
      SplashFormRequest
      {'splash':{'http_method':'POST'}


      基于

      现在,Splash支持POST请求。请尝试
      SplashFormRequest
      {'splash':{'http_method':'POST'}


      根据

      我确实看到了
      inspect\u响应
      工作,外壳打开。你那边发生了什么?我从我的
      视图(响应)
      中添加了一个屏幕截图,然后是单击搜索按钮后实际应该发生的事情的屏幕截图。你看到的反应和你这边的第二个屏幕截图一样吗?我看到的只是第一个。我确实看到
      inspect\u响应
      工作,外壳打开了。你那边发生了什么?我从我的
      视图(响应)
      中添加了一个屏幕截图,然后是单击搜索按钮后实际应该发生的事情的屏幕截图。你看到的反应和你这边的第二个屏幕截图一样吗?我看到的只是第一个好吧我又迷路了。我一直在使用
      FormRequest.from_response()
      获取所有cookie、会话id和其他表单字段。如何使用我通过
      FormRequest.from\u response
      获得的所有表单数据参数,向我的
      流程
      函数发出
      请求
      ?因为我只能对
      请求使用
      meta
      ,而不能对
      表单请求使用
      :s@MetalloyD
      FormRequest
      是常规
      请求的子类
      -您应该能够使用与常规
      请求
      相同的
      meta
      值。目前,我很难在本地设置splash容器,因此无法重现该问题。你现在有什么代码(在问题或要点中张贴)?谢谢,我已经把代码改成我试过的了。我还修改了这个问题,使其更具体地介绍了Splash。好的,请查看更新的答案。希望能有帮助。非常感谢alecxe!:那么,如果我理解的话,这种类型的用例不能与Splash一起使用?刮痧可以和硒一起用于这些类型的刮伤吗?因为Scrapy真的很快!相比之下,硒的吸收速度相当慢。好吧,我又迷路了。我一直在使用
      FormRequest.from_response()
      获取所有cookie、会话id和其他表单字段。如何使用我通过
      FormRequest.from\u response
      获得的所有表单数据参数,向我的
      流程
      函数发出
      请求
      ?因为我只能对
      请求使用
      meta
      ,而不能对
      表单请求使用
      :s@MetalloyD
      FormRequest
      是常规
      请求的子类
      -您应该能够使用与常规
      请求
      相同的
      meta
      值。目前,我在本地设置飞溅容器很难,无法再现问题。你现在有什么代码(在问题或要点中张贴)?谢谢,我已经把代码改成我试过的了。我还修改了这个问题,使其更具体地介绍了Splash。好的,请查看更新的答案。希望能有帮助。非常感谢alecxe!:那么,如果我理解的话,这种类型的用例不能与Splash一起使用?刮痧可以和硒一起用于这些类型的刮伤吗?因为刮痧'