【问题标题】:Scrapy + selenium requests twice for each urlScrapy + selenium 为每个 url 请求两次
【发布时间】:2018-11-15 18:46:53
【问题描述】:
import scrapy 
from selenium import webdriver

class ProductSpider(scrapy.Spider):
    name = "product_spider"
    allowed_domains = ['ebay.com']
    start_urls = ['http://www.ebay.com/sch/i.html?_odkw=books&_osacat=0&_trksid=p2045573.m570.l1313.TR0.TRC0.Xpython&_nkw=python&_sacat=0&_from=R40']

    def __init__(self):
        self.driver = webdriver.Firefox()

    def parse(self, response):
        self.driver.get(response.url)

        while True:
            next = self.driver.find_element_by_xpath('//td[@class="pagn-next"]/a')

            try:
                next.click()

                # get the data and write it to scrapy items
            except:
                break

        self.driver.close()

selenium with scrapy for dynamic page

这个解决方案效果很好,但它两次请求相同的 url,一次是由 scrapy 调度程序请求,另一次是由 selenium web 驱动程序请求。

与没有 selenium 的 scrapy 请求相比,完成这项工作需要两倍的时间。如何避免这种情况?

【问题讨论】:

  • 如果你已经在使用 Selenium,为什么还要使用 scrapy?
  • @VMRuiz scrapy 不仅仅是请求响应和 html 解析。它具有更多功能,最有趣的是并发性。
  • 这种情况下,如果只想渲染网页可以使用scrapy + splash:splash.readthedocs.io/en/stable
  • 我使用了 splash 但我无法获取一个站点的结果。其中 chrome 和 firefox 是众所周知的浏览器,它们将提供 100% 的结果。

标签: python selenium web-scraping scrapy


【解决方案1】:

这里有一个技巧可以用来解决这个问题。

为 selenium 创建一个网络服务,在本地运行它

from flask import Flask, request, make_response
from flask_restful import Resource, Api
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

app = Flask(__name__)
api = Api(app)

class Selenium(Resource):
    _driver = None

    @staticmethod
    def getDriver():
        if not Selenium._driver:
            chrome_options = Options()
            chrome_options.add_argument("--headless")

            Selenium._driver = webdriver.Chrome(chrome_options=chrome_options)
        return Selenium._driver

    @property
    def driver(self):
        return Selenium.getDriver()

    def get(self):
        url = str(request.args['url'])

        self.driver.get(url)

        return make_response(self.driver.page_source)

api.add_resource(Selenium, '/')

if __name__ == '__main__':
    app.run(debug=True)

现在http://127.0.0.1:5000/?url=https://stackoverflow.com/users/5939254/yash-pokar 将返回您使用 selenium Chrome/Firefox 驱动程序编译的网页。

现在我们的蜘蛛会是什么样子,

import scrapy
import urllib


class ProductSpider(scrapy.Spider):
    name = 'products'
    allowed_domains = ['ebay.com']
    urls = [
        'http://www.ebay.com/sch/i.html?_odkw=books&_osacat=0&_trksid=p2045573.m570.l1313.TR0.TRC0.Xpython&_nkw=python&_sacat=0&_from=R40',
    ]

    def start_requests(self):
        for url in self.urls:
            url = 'http://127.0.0.1:5000/?url={}'.format(urllib.quote(url))
            yield scrapy.Request(url)

    def parse(self, response):
        yield {
            'field': response.xpath('//td[@class="pagn-next"]/a'),
        }

【讨论】:

    猜你喜欢
    • 2019-03-08
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多