使用 Splash 将 POST 抓取到 Javascript 生成的表单
Scrapy POST to a Javascript generated form using Splash
我有以下 spider,它几乎应该 Post 到一个表单。
我似乎无法让它工作。当我通过 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)
我得到的是这样的回应:
我应该得到的结果是这样的:
当我将 dealer_search_page()
替换为 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
并且程序在到达我的 process()
函数中的 inspect_response()
之前退出。
错误提示 Splash 尚不支持 POST
。
Splash
是否适用于此用例,还是我应该使用 Selenium
?
您可以使用 selenium
来处理它。这是一个完整的工作示例,其中我们使用与您的 Scrapy 代码中相同的搜索参数提交表单,并在控制台上打印结果:
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 号码 table:
08502557052
08451314461
...
08734200736
请注意,您使用 selenium
实现自动化的浏览器可以是无头的 - PhantomJS
或 虚拟显示.
上的常规浏览器
回答初始问题(编辑前):
我在“经销商搜索”页面上看到的内容 - 表单及其字段由在浏览器中执行的一堆 JavaScript 脚本构成。 Scrapy无法执行JS,这部分需要你帮忙。我很确定 Scrapy+Splash 在这种情况下就足够了,您不需要进入浏览器自动化。这是一个将 Scrapy 与 Splash 一起使用的工作示例:
现在 Splash 支持 POST 请求。尝试 SplashFormRequest
或 {'splash':{'http_method':'POST'}}
我有以下 spider,它几乎应该 Post 到一个表单。 我似乎无法让它工作。当我通过 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)
我得到的是这样的回应:
我应该得到的结果是这样的:
当我将 dealer_search_page()
替换为 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
并且程序在到达我的 process()
函数中的 inspect_response()
之前退出。
错误提示 Splash 尚不支持 POST
。
Splash
是否适用于此用例,还是我应该使用 Selenium
?
您可以使用 selenium
来处理它。这是一个完整的工作示例,其中我们使用与您的 Scrapy 代码中相同的搜索参数提交表单,并在控制台上打印结果:
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 号码 table:
08502557052
08451314461
...
08734200736
请注意,您使用 selenium
实现自动化的浏览器可以是无头的 - PhantomJS
或 虚拟显示.
回答初始问题(编辑前):
我在“经销商搜索”页面上看到的内容 - 表单及其字段由在浏览器中执行的一堆 JavaScript 脚本构成。 Scrapy无法执行JS,这部分需要你帮忙。我很确定 Scrapy+Splash 在这种情况下就足够了,您不需要进入浏览器自动化。这是一个将 Scrapy 与 Splash 一起使用的工作示例:
现在 Splash 支持 POST 请求。尝试 SplashFormRequest
或 {'splash':{'http_method':'POST'}}