【问题标题】:Scraping dynamic content using selenium and Scrapy with multiple start URL's使用 selenium 和具有多个起始 URL 的 Scrapy 抓取动态内容
【发布时间】:2016-06-24 06:39:08
【问题描述】:

我的任务是为一个物业站点构建一个刮板,将结果存储起来以供以后处理。有问题的站点是一个国家站点,不会在一次搜索中产生其所有内容,它希望您在提供结果之前提供一个区域。为了解决这个问题,我使用scrapy创建了一个刮板,它使用多个起始URL直接将我带到我感兴趣的区域。该站点也是动态填充的,所以我使用selenium在页面上呈现javascript,然后跟随下一个按钮,直到每个区域的刮刀完成。 当只有一个起始 URL 时,这很有效,但是一旦有多个 URL,我就会遇到问题。最初刮板工作正常,但是在 webdriver 完成跟随“下一步”按钮到区域末尾(例如,单个区域可能有 20 个页面)之前,刮板仅部分移动到下一个区域(起始 URL)抓取第一个区域的内容。 我已经广泛寻找解决方案,但是我还没有看到有人遇到这个特殊问题。任何建议都将受到欢迎。示例代码如下:

from scrapy.spider                  import CrawlSpider
from scrapy.http                    import TextResponse
from scrapy.selector                import HtmlXPathSelector
from selenium                       import webdriver
from selenium.webdriver.common.by   import By
from selenium.webdriver.support.ui  import WebDriverWait
from selenium.webdriver.support     import expected_conditions as EC
from selenium.common.exceptions     import TimeoutException
import time
from selenium                       import webdriver
from selenium                       import selenium
from selenium_spider.items          import DemoSpiderItem
from selenium.webdriver.support.ui  import WebDriverWait
from selenium.webdriver.support     import expected_conditions as EC
from selenium.common.exceptions     import TimeoutException
import sys

class DemoSpider(CrawlSpider):
    name="Demo"
    allowed_domains = ['example.com']
    start_urls= ["http://www.example.co.uk/locationIdentifier=REGION    1234",
    "http://www.example.co.uk/property-for-sale/locationIdentifier=REGION    5678"]

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

    def __del__(self):
        self.selenium.stop()

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


        result = response.xpath('//*[@class="l-searchResults"]')
        source = 'aTest'
        while True:
            try:
                element = WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR,".pagination-button.pagination-direction.pagination-direction--next"))
            )
                print "Scraping new site --------------->", result
                print "This is the result----------->", result
                for properties in result:
                    saleOrRent = properties.xpath('//*[@class = "property-title"]/text()').extract()
                    addresses = properties.xpath('//*[@class="property-address"]/text()').extract()
                    if saleOrRent:
                        saleOrRent = saleOrRent[0]
                        if 'for sale' in saleOrRent:
                            saleOrRent = 'For Sale'
                        elif 'to rent' in saleOrRent:
                            saleOrRent = 'To Rent'
                for a in addresses:
                    item = DemoSpiderItem()
                    address = a
                    item ["saleOrRent"] = saleOrRent
                    item ["source"] = source
                    item ["address"] = address
                    item ["response"] = response
                    yield item
                element.click()
            except TimeoutException:
                    break

【问题讨论】:

  • 我也有同样的问题!你找到解决方案了吗?我现在也在找,如果有什么我会告诉你的。

标签: javascript selenium webdriver scrapy


【解决方案1】:

我实际上只是玩了一下,结果比我想象的要容易。 您只在 start_urls 中传递一个初始 url,创建单独的手动后续 url 列表以生成手动 Request,并使用 parse 函数作为回调,并使用计数器访问 @987654324 中正确 url 的索引@ 将其传递给请求。

这样,您可以自行决定何时加载下一个 url,例如一次。你没有更多的结果。这里唯一的缺点是它是连续的,但是很好...... :-)

见代码:

import scrapy from scrapy.http.request 
import Request from selenium 
import webdriver from scrapy.selector 
import Selector from products_scraper.items import ProductItem

class ProductsSpider(scrapy.Spider):
    name = "products_spider"
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com/first']

    global manual_urls
    manual_urls = [
    'http://www.example.com/second',
    'http://www.example.com/third'
    ]

    global manual_url_index 
    manual_url_index = 0

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

    def parse(self, response):

        self.driver.get(response.url)

        hasPostings = True

        while hasPostings:
            next = self.driver.find_element_by_xpath('//dd[@class="next-page"]/a')

            try:
                next.click()
                self.driver.set_script_timeout(30)
                products = self.driver.find_elements_by_css_selector('.products-list article')

                if(len(products) == 0): 
                    if(manual_url_index < len(manual_urls)):
                        yield Request(manual_urls[manual_url_index],
                            callback=self.parse)
                        global manual_url_index
                        manual_url_index += 1

                    hasPostings = False

                for product in products:
                    item = ProductItem()
                    # store product info here
                    yield item 

            except Exception, e:
                print str(e)
                break



        def spider_closed(self, spider):
            self.driver.quit()

【讨论】:

    猜你喜欢
    • 2015-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 2021-04-28
    • 2016-09-15
    • 1970-01-01
    相关资源
    最近更新 更多