Python 将selenium驱动程序传递给scrapy
我花了很长时间试图弄明白这一点,但没有结果。我已经读了很多关于传回HtmlResponse和使用selenium中间件的书,但是很难理解如何构造代码并将其实现到我的解决方案中 这是我的蜘蛛代码:Python 将selenium驱动程序传递给scrapy,python,selenium,scrapy,Python,Selenium,Scrapy,我花了很长时间试图弄明白这一点,但没有结果。我已经读了很多关于传回HtmlResponse和使用selenium中间件的书,但是很难理解如何构造代码并将其实现到我的解决方案中 这是我的蜘蛛代码: import scrapy from selenium import webdriver from selenium.webdriver.common.keys import Keys from time import sleep count = 0 class ContractSpider(scr
import scrapy
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
count = 0
class ContractSpider(scrapy.Spider):
name = "contracts"
def start_requests(self):
urls = [
'https://www.contractsfinder.service.gov.uk/Search/Results',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def __init__(self):
self.driver = webdriver.Firefox()
self.driver.get("https://www.contractsfinder.service.gov.uk/Search/Results")
elem2 = self.driver.find_element_by_name("open")
elem2.click()
sleep(5)
elem = self.driver.find_element_by_name("awarded")
elem.click()
sleep(5)
elem3 = self.driver.find_element_by_id("awarded_date")
elem3.click()
sleep(5)
elem4 = self.driver.find_element_by_name("awarded_from")
elem4.send_keys("01/03/2018")
elem4.send_keys(Keys.RETURN)
sleep(5)
elem5 = self.driver.find_element_by_name("awarded_to")
elem5.send_keys("16/03/2018")
elem5.send_keys(Keys.RETURN)
sleep(5)
elem6 = self.driver.find_element_by_name("adv_search")
self.driver.execute_script("arguments[0].scrollIntoView(true);", elem6)
elem6.send_keys(Keys.RETURN)
def parse(self, response):
global count
count += 1
strcount = str(count)
page = self.driver.get(response.url)
filename = strcount+'quotes-%s.html' % page
with open(filename, 'wb') as f:
f.write(response.body)
self.log('Saved file %s' % filename)
for a in response.css('a.standard-paginate-next'):
yield response.follow(a, callback=self.parse)
selenium部分在调用firefox时工作,各种java交互正在进行,最后一页的结果已经加载
代码中的刮擦部分似乎在工作(它找到了selenium加载的firefox webdriver的next按钮并点击了——我可以通过观看webdriver firefox本身看到这一点)——但是,实际的刮擦发生了(它正在将HTML保存到我的c:\驱动器上)正在从firefox webdriver中单独删除URL“”,并且没有selenium诱导的java交互
我想我理解了一些原因,比如在start_请求中,我指的是原始URL,这意味着selenium加载的页面没有被蜘蛛使用,但是,每次我试图通过阅读stackoverflow中的各种不同方法从webdriver中创建响应时,我都会遇到各种错误,因为我的理解不够好-我想我会发布一个版本,其中selenium&scrapy元素正在做些什么,但是,有人能解释一下并告诉我链接这两个元素的最佳方法吗?即,一旦selenium完成,使用firefox webdriver加载的页面并将其传递给scrapy来完成它的工作?非常感谢您的反馈。正如您所说,scrapy打开的是您的初始url,而不是由Selenium修改的页面 如果您想从Selenium获取页面,应该使用driver.page\u source.encode('utf-8')(编码不是强制性的)。您也可以将其与刮片选择器一起使用:
response = Selector(text=driver.page_source.encode('utf-8'))
之后,您可以像以前一样使用响应
编辑:
我会尝试这样的方法(注意,我还没有测试代码):
正如您所说,scrapy打开的是您的初始url,而不是由Selenium修改的页面 如果您想从Selenium获取页面,应该使用driver.page\u source.encode('utf-8')(编码不是强制性的)。您也可以将其与刮片选择器一起使用:
response = Selector(text=driver.page_source.encode('utf-8'))
之后,您可以像以前一样使用响应
编辑:
我会尝试这样的方法(注意,我还没有测试代码):
结合来自和其他人的解决方案,以下是我的测试代码:
import scrapy
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
...
def __init__(self, name=None, **kwargs):
super(MySpider, self).__init__(name, **kwargs)
self.driver = webdriver.Chrome()
@staticmethod
def get_selenium_response(driver, url):
driver.get(url)
# in case of explicit amount of time
# time.sleep(5)
# in case of wait until element been found
try:
def find(driver):
table_el = driver.find_element_by_xpath('//*[@id="table_el"]')
if table_el:
return table_el
else:
return False
element = WebDriverWait(driver, 5).until(find)
return driver.page_source.encode('utf-8')
except:
driver.quit()
def parse(self, response):
response = scrapy.Selector(
text=self.get_selenium_response(self.driver, response.url))
# ...parse response as normally
结合来自和其他人的解决方案,以下是我的测试代码:
import scrapy
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
...
def __init__(self, name=None, **kwargs):
super(MySpider, self).__init__(name, **kwargs)
self.driver = webdriver.Chrome()
@staticmethod
def get_selenium_response(driver, url):
driver.get(url)
# in case of explicit amount of time
# time.sleep(5)
# in case of wait until element been found
try:
def find(driver):
table_el = driver.find_element_by_xpath('//*[@id="table_el"]')
if table_el:
return table_el
else:
return False
element = WebDriverWait(driver, 5).until(find)
return driver.page_source.encode('utf-8')
except:
driver.quit()
def parse(self, response):
response = scrapy.Selector(
text=self.get_selenium_response(self.driver, response.url))
# ...parse response as normally
谢谢Alex-几个问题-1)在我当前的spider中,代码应该放在哪里,2)我的启动请求应该是什么样子/我还需要包含启动请求吗?Alex说的是正确的,我建议您使用wait.till,而不是在代码中使用很多sleep;)Alex-再次感谢您提供代码,经过数小时的编辑和尝试,我仍然无法让脚本正常工作。只是重申一下我正在尝试的过程——我想加载firefox webdriver,转到URL,应用所有java——加载最终页面——将此发送给scrapy并通过过滤(通过selenium)结果进行分页——不确定我是否清楚这一点。我很难理解-我可以进行尽可能多的解析,但不断出现错误,例如Seleniu_response=Selector(..)中未定义“url”。请尝试运行代码进行调试好吗?感谢Hanks Alex-几个问题-1)在我当前的spider中,代码应该放在哪里,2)我的启动请求应该是什么样子/我还需要包括启动请求吗?Alex说的是正确的,我建议您使用wait.until,而不是在代码中使用很多sleep;)Alex-再次感谢您提供代码,经过数小时的编辑和尝试,我仍然无法让脚本正常工作。只是重申一下我正在尝试的过程——我想加载firefox webdriver,转到URL,应用所有java——加载最终页面——将此发送给scrapy并通过过滤(通过selenium)结果进行分页——不确定我是否清楚这一点。我很难理解-我可以进行尽可能多的解析,但不断出现错误,例如Seleniu_response=Selector(..)中未定义“url”。请尝试运行代码进行调试好吗?谢谢