Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将selenium驱动程序传递给scrapy_Python_Selenium_Scrapy - Fatal编程技术网

Python 将selenium驱动程序传递给scrapy

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

我花了很长时间试图弄明白这一点,但没有结果。我已经读了很多关于传回HtmlResponse和使用selenium中间件的书,但是很难理解如何构造代码并将其实现到我的解决方案中

这是我的蜘蛛代码:

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”。请尝试运行代码进行调试好吗?谢谢