2017-04-25 9 views
1

저는 파이썬과 치료의 초보자입니다. 도움이 필요합니다. 제품 목록을 추출해야하지만, 그 사이트는 ajax로 text/html 요청을 실행하고 새로운 html로 새로운 제품을로드하는 끝에 "더 많은 제품보기"제품을 제공합니다.무한 스크롤링으로 데이터 추출하기 Ajax with Scrapy

import scrapy 
from scrapy.http import Request 


class ProdSpider(scrapy.Spider): 
name = "easy" 
allowed_domains = ["easy.com.ar"] 
start_urls = ["https://www.easy.com.ar/webapp/wcs/stores/servlet/es/easyar/search/AjaxCatalogSearchResultContentView?searchTermScope=&searchType=1002&filterTerm=&orderBy=&maxPrice=&showResultsPage=true&langId=-5&sType=SimpleSearch&metaData=&pageSize=12&manufacturer=&resultCatEntryType=&catalogId=10051&pageView=image&searchTerm=&minPrice=&categoryId=39652&storeId=10151&beginIndex=12"] 
beginIndex_index = 12 

def parse(self, response): 
    SECTION_SELECTOR = '.thumb-product' 
    for soar in response.css(SECTION_SELECTOR): 

      Link = 'div.dojoDndItem a ::attr(href)' 
      # Marca = 'p.brand a ::text' 
      Nombre = 'div.thumb-name a ::text' 
      # Link = 'p.brand a ::attr(href)' 
      # SKU = './/p[@class="sku"]/text()' #p.sku ::text' 
      Price = './/span[@id="tarj-mas-edit"]/text()' #["0"].parentElement.innerText .//span[@class="thumb-price-e"]/text() 

      yield { 
       'Link': soar.css(Link).extract_first(), 
      # 'Marca': soar.css(Marca).extract_first(), 
       'Nombre': soar.css(Nombre).re_first(r'\n\s*(.*)'), # Limpia espacios y caracteres especiales 
      # 'Link': soar.css(Link).extract_first(), 
      # 'SKU': soar.xpath(SKU).re_first(r'SKU:\s*(.*)'), 
       'Price': soar.xpath(Price).re_first(r'\n\s*(.*)'), 
       } 
    # here if no products are available , simply return, means exiting from 
    # parse and ultimately stops the spider 


    self.beginIndex_index += 12 
    if beginIndex_index: 
     yield Request(url="https://www.easy.com.ar/webapp/wcs/stores/servlet/es/easyar/search/AjaxCatalogSearchResultContentView?searchTermScope=&searchType=1002&filterTerm=&orderBy=&maxPrice=&showResultsPage=true&langId=-5&sType=SimpleSearch&metaData=&pageSize=12&manufacturer=&resultCatEntryType=&catalogId=10051&pageView=image&searchTerm=&minPrice=&categoryId=39652&storeId=10151&beginIndex=%s" % (self.beginIndex_index + 12), 
         callback=self.parse) 

위의 코드로 시도했지만 12 개 제품 만 캡처되었습니다. url에서 변경되는 유일한 매개 변수는 "beginIndex = 12"이며, Y는 제품 목록이 끝날 때까지 URL에 +12를 더합니다. 나는이 문제에 갇혀있다!

감사합니다.

답변

3

나는 당신이 보기 더 버튼을 '클릭'과 거미의 내부에 더 많은 데이터를로드 할 수 있도록, 셀레늄를 사용하는 것이 좋습니다. 다음은 거미의 샘플입니다 (나는 그것을 테스트하지 않았다,하지만 그것은 일반적인 생각) :

import scrapy 
from selenium import webdriver 
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary 


class ProdSpider(scrapy.Spider): 
    name = "easy" 
    allowed_domains = ["easy.com.ar"] 
    start_urls = ["https://www.easy.com.ar/webapp/wcs/stores/servlet/es/easyar/search/aditivos-y-lubricantes"] 

    def __init__(self): 
     super(ProdSpider, self).__init__() 
     binary = FirefoxBinary('C:/Program Files (x86)/Mozilla Firefox/firefox.exe') 
     self.wb = webdriver.Firefox(firefox_binary=binary) 

    def parse(self, response): 
     self.wb.get(response.url) 
     while True: 
      view_more_button = self.wb.find_element_by_xpath('//*[@id="Search_Result_div"]/div[2]/div[9]/input') 
      if not view_more_button: 
       break 
      view_more_button.click() 
      #extract your data here... 
1

당신은 그것을 얻었다!

URL에 pageSize이라는 다른 매개 변수가 있습니다. 나는 그것을 테스트했고 웹 사이트에서는 최대 50까지 설정할 수 있습니다.

, 당신은 단지 다른 요청 항복하기 전에 response.css(SECTION_SELECTOR)의 항목이있는 경우 테스트 할 수 있습니다 중지 할 때 알고 :이 코드를 테스트하지 않았다

import scrapy 
from scrapy.http import Request 
from scrapy import Selector 


class ProdSpider(scrapy.Spider): 
    name = "easy" 
    allowed_domains = ["easy.com.ar"] 

    url = "https://www.easy.com.ar/webapp/wcs/stores/servlet/es/easyar/search/AjaxCatalogSearchResultContentView?searchTermScope=&searchType=1002&filterTerm=&orderBy=&maxPrice=&showResultsPage=true&langId=-5&sType=SimpleSearch&metaData=&pageSize=50&manufacturer=&resultCatEntryType=&catalogId=10051&pageView=image&searchTerm=&minPrice=&categoryId=39652&storeId=10151&beginIndex={pagenum}" 

    product_fields_xpath = { 
    'Link': '//a[contains(@id, "CatalogEntry")]/@href', 
    'Nombre': '//a[contains(@id, "CatalogEntry")]/text()', 
    'Price': './/span[@class="thumb-price-e"]/text()' 
    } 

    section_selector = '//div[@class="thumb-product"]' 

    begin_index = 0 

    def start_request(self): 
    yield Request(url=url.format(pagenum=self.begin_index), method='GET', callback=self.parse) 

    def parse(self, response): 
    products = response.xpath(self.section_selector).extract() 
    n_items = 0 
    for product in products: 
     n_items += 1 
     sel = Selector(text=product) 
     item = dict() 
     for k, v in self.product_fields_xpath.iteritems(): 
     item[k] = sel.xpath(v).extract_first() 
     yield item 

    self.begin_index += 50 

    if n_items > 0: 
     yield Request(url=url.format(pagenum=self.begin_index), method='GET', callback=self.parse) 

을,하지만 난 당신이 무슨 뜻인지 이해 바랍니다 .

+0

안녕하세요 @ 벤자민. 당신의 도움을 주셔서 감사합니다! 이 코드를 테스트했지만 작동하지 않았습니다! 최소 제품은 12이고, 다음 ajax html load는 24로 바뀐다. –

+0

나는'css' 추출물과'xpath' 사이의 혼합 때문에 작동하지 않는다고 생각한다. 최소한, 페이지 당 제품 수를 50으로 설정했습니다. 그 후, beginIndex 매개 변수에 50을 추가합니다. 일반적으로 페이지별로 : 0 -> 49, 50 -> 99, 100 -> 149 등 ... 그리고 각 페이지에는 동일한 제품이 없습니다. –

+0

위의 코드를 수정하는 데 도움이됩니다. 나는 xpath (그냥 personnal 느낌)을 사용하는 것을 선호하며 Selector를 사용하여 HTML 문자열에서 데이터를 추출합니다. –