Как извлечь данные с динамических веб-сайтов, таких как Flipkart, с помощью селена и Scrapy?

Поскольку Flipkart.com показывает только от 15 до 20 результатов на 1-й странице, а при прокрутке показывает больше результатов. Scrapy успешно извлекает результаты 1-й страницы, но не следующих страниц. Я пытался использовать Selenium для этого, но не смог добиться успеха. Вот мой код: -

from scrapy.spider import Spider

from scrapy.selector import Selector

from flipkart.items import FlipkartItem

from scrapy.spider import BaseSpider

from selenium import webdriver

class FlipkartSpider(BaseSpider):
    name = "flip1"
    allowed_domains = ["flipkart.com"]
    start_urls = [
        "http://www.flipkart.com/beauty-and-personal-care/personal-care-appliances/hair-dryers/pr?sid=t06,79s,mh8&otracker=nmenu_sub_electronics_0_Hair%20Dryers"
]

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

    def parse(self, response):
        sel = Selector(response)
        self.driver.get(response.url)
        while True:
            next = self.driver.find_element_by_xpath('//div[@id="show-more-results"]')
            try:

                sites = sel.select('//div[@class="gd-col gu12 browse-product fk-inf-scroll-item"] | //div[@class="pu-details lastUnit"]')
                for site in sites:
                    item = FlipkartItem()
                    item['title'] = site.select('div//a[@class="lu-title"]/text() | div[1]/a/text()').extract()
                    item['price'] = site.select('div//div[@class="pu-price"]/div/text() | div//div[@class="pu-final"]/span/text()').extract()
                    yield item
                next.wait_for_page_to_load("30")
            except:
                break
            self.driver.close()

, Мои items.py: -

import scrapy
class FlipkartItem(scrapy.Item):
    title=scrapy.Field()
    price=scrapy.Field()

и следующий вывод я получаю только для 15 элементов: -

[{"price": ["Rs. 599"], "title": ["\n Citron Elegant 1400 W HD001 Hair Dryer (Pink)\n "]},

{"price": ["Rs. 799"], "title": ["\n Citron Vogue 1800 W HD002 Hair Dryer (White)\n "]},

{"price": ["Rs. 645"], "title": ["\n Philips HP8100/00 Hair Dryer (Blue)\n "]},

{"price": ["Rs. 944"], "title": ["\n Philips HP8111/00 Hair Dryer\n "]},

{"price": ["Rs. 171"], "title": ["\n Nova Professional With 2 Speed NV-1290 Hair Dryer (Pink...\n "]},

{"price": ["Rs. 175"], "title": ["\n Nova NHD 2840 Hair Dryer\n "]},

{"price": ["Rs. 775"], "title": ["\n Philips HP 8112 Hair Dryer\n "]},

{"price": ["Rs. 1,925"], "title": ["\n Philips HP8643/00 Miss Fresher's Pack Hair Straightener...\n "]},

{"price": ["Rs. 144"], "title": ["\n Nova Foldable N-658 Hair Dryer (White, Pink)\n "]},

{"price": ["Rs. 1,055"], "title": ["\n Philips HP8100/46 Hair Dryer\n "]},

{"price": ["Rs. 849"], "title": ["\n Panasonic EH-ND12-P62B Hair Dryer (Pink)\n "]},

{"price": ["Rs. 760"], "title": ["\n Panasonic EH-ND11 Hair Dryer (White)\n "]},

{"price": ["Rs. 1,049"], "title": ["\n Panasonic EH-ND13-V Hair Dryer (Violet)\n "]},

{"price": ["Rs. 1,554"], "title": ["\n Philips 1600 W HP4940 Hair Dryer (White & Light Pink)\n "]},

{"price": ["Rs. 2,008"], "title": ["\n Philips Kerashine HP8216/00 Hair Dryer\n "]}]

person Mercury    schedule 24.01.2015    source источник
comment
Возможно, вы могли бы сначала спросить их, поделятся ли они с вами своими данными? Если вы им понравитесь, они, вероятно, предоставят вам лучший способ доступа к данным, а если нет, у вас, вероятно, будет война, в результате которой они продолжат блокировать вашего паука, и вам придется продолжать работать над тем, чтобы обойти это.   -  person John Mee    schedule 24.01.2015
comment
@John, они уже поделились своими данными через веб-сайт. Я просто делаю скрипт с использованием python, Scrappy и Selenium для автоматического извлечения их данных с html-страниц в файл txt или .json.   -  person Mercury    schedule 02.02.2015
comment
я работаю над тем же проектом....   -  person Nakshatra    schedule 22.06.2015


Ответы (3)


Мне это удалось по-другому. См. мой код для дальнейшего справки. Работает нормально для полного сайта..

class FlipkartSpider(BaseSpider):
    name = "flip1"
    allowed_domains = ["flipkart.com"]
    start_urls = [
        "http://www.flipkart.com/tablets/pr?sid=tyy%2Chry&q=mobile&ref=b8b64676-065a-445c-a6a1-bc964d5ff938"
    ]
    '''def is_element_present(self, finder, selector, wait_time=None):
        wait_time = wait_time or self.wait_time
        end_time = time.time() + wait_time
        while time.time() < end_time:
            if finder(selector):
                return True
        return False
        def is_element_present_by_xpath(self, xpath, wait_time=None):
        return self.is_element_present(self.find_by_xpath, xpath, wait_time)
        '''
    def __init__(self):
        self.driver = webdriver.Firefox()


    def parse(self, response):
        sel = Selector(response) 
        self.driver.get(response.url)
        block="block"
        hyper="http://www.flipkart.com"
        print hyper
        #i=0
        while True:
            self.driver.execute_script("window.scrollTo(10000000,10000000)")
            self.driver.set_page_load_timeout(10000)
            try:
                show = self.driver.find_element_by_xpath('//div[@id="show-more-results"]').value_of_css_property('display')
                if show==block:
                    self.driver.find_element_by_xpath('//div[@id="show-more-results"]').click()
                no_more = self.driver.find_element_by_xpath('//*[@id="no-more-results" and @class="dont-show"]').value_of_css_property('display')
                if no_more==block:
                    break;
                time.sleep(5)
                self.driver.execute_script("window.scrollTo(10000000,10000000)")

                self.driver.set_page_load_timeout(10000)
                #if i==7:
                #   break
            except NoSuchElementException:
                print "pungi"
                break
        #down = self.driver.find_element_by_xpath('//div[@id="show-more-results"]')
        #location = down.location
        #self.((JavascriptExecutor) driver).executeScript("window.scrollBy(10000,10000);");
        #next = self.driver.find_element_by_xpath('//div[@id="show-more-results"]')
        response = TextResponse(url=response.url, body=self.driver.page_source, encoding='utf-8')
        try:
            #self.driver.set_page_load_timeout(10000)
            #driver.execute_script("window.scrollTo(0, location.get('y')")
            sites = response.xpath('//div[@class="gd-col gu12 browse-product fk-inf-scroll-item"] | //div[@class="pu-details lastUnit"] |  //div[@class="pu-visual-section"]')
            for site in sites:
                item = FlipkartItem()
                item['title'] = site.xpath('div//a[@class="lu-title"]/text() | div[1]/a/text()').extract()
                item['price'] = site.xpath('div//div[@class="pu-price"]/div/text() | div//div[@class="pu-final"]/span/text()').extract()
                item['rating'] = site.xpath('div[@class="pu-rating"]/div/@title').extract()
                item['image'] = site.xpath('a/img/@src').extract()
                data = site.xpath('a/@href').extract()
                print data
                item['link'] = data

                #print rating
                yield item
            '''for site in sites:
                item = FlipkartItem()
                item['title'] = site.xpath('div//a[@class="lu-title"]/text() | div[1]/a/text()').extract()
                item['price'] = site.xpath('div//div[@class="pu-price"]/div/text() | div//div[@class="pu-final"]/span/text()').extract()
                item['rating'] = site.xpath('div[@class="pu-rating"]/div/@title').extract()
                #print rating
                yield item'''
            #next.click()
            #self.driver.execute_script("window.scrollTo(10000000,10000000)")
        except:
            #break
            a=10
        self.driver.close()
person Nakshatra    schedule 22.06.2015

Вы должны заставить веб-драйвер загрузить больше результатов. Чтобы иметь возможность взаимодействовать с другими результатами, веб-драйвер должен прокручивать страницу, пока не появятся элементы.

Код для прокрутки:

driver.execute_script("window.scrollTo(0, location.get('y')")

Чтобы решить, где прокручивать, вы можете найти элемент в нижней части страницы (например, нижний колонтитул) и продолжить прокрутку до него. Чтобы получить координаты элемента, вы можете использовать местоположение свойства Webelement.

driver = webdriver.Firefox()
down = driver.find_element_by_xpath("//someXpath")
location = down.location
person aberna    schedule 24.01.2015
comment
@Mercury Я заметил понижение рейтинга. что-то не работает в предложенном решении, которое уже принято? - person aberna; 02.02.2015
comment
@arberna, он успешно загружает продукты с других страниц (только в браузере), но скраппи не сканирует их в файл .json. По-прежнему в файл выводятся только записи 1-й страницы. - person Mercury; 02.02.2015
comment
В своем вопросе вы указывали на проблему с Selenium, чтобы перейти на следующую страницу. Мой ответ, как и другой, предложил решить эту проблему. Для Scrapy, когда вы попадаете на новую страницу, вам необходимо принудительно обновить текущий URL-адрес и проанализировать новый код. Пример здесь: stackoverflow.com /вопросы/25215623/ - person aberna; 02.02.2015
comment
Спасибо, я понял, что мой вопрос касался только селена. - person Mercury; 02.02.2015
comment
@Mercury, как я предложил, проверьте код в аналогичном вопросе. Ключ self.driver.refresh() , yield Request(self.driver.current_url, callback=self.parse) - person aberna; 02.02.2015

Вы можете использовать Javascript для прокрутки страницы вниз.

Следующий код будет прокручивать страницу вниз на 10000,10000 в направлении x и y. Поскольку 10000 — большое число, оно перенесет вас в конец страницы. Как только вы окажетесь внизу, флипкарт запускает запрос AJAX для загрузки большего количества элементов.

window.scrollBy(10000,10000);

Я не уверен, как мы можем сделать это в scrapy, но с помощью селена это легко.

Вот код

((JavascriptExecutor) driver).executeScript("window.scrollBy(10000,10000);");
person h4k3r    schedule 24.01.2015