Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.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 Scrapy:蜘蛛优化_Python_Web Scraping_Scrapy_Scrapy Spider - Fatal编程技术网

Python Scrapy:蜘蛛优化

Python Scrapy:蜘蛛优化,python,web-scraping,scrapy,scrapy-spider,Python,Web Scraping,Scrapy,Scrapy Spider,我正试图废弃一个电子商务网站,我分两步来做 本网站的结构如下: 主页具有指向“族项目”和“子族项目”页面的链接 每个族和子族页面都有一个已分页的产品列表 现在我有两个蜘蛛: GeneralSpider获取主页链接并存储它们 ItemSpider从每个页面获取元素 我对Scrapy完全是新手,我正在跟随一些教程来实现这一点。我想知道解析函数有多复杂,规则是如何工作的。我的蜘蛛现在看起来像: 通用皮德尔: 项目蜘蛛: 让爬行器跟随url分页的最佳方法是什么 如果分页为JQueryJQuer

我正试图废弃一个电子商务网站,我分两步来做

本网站的结构如下:

  • 主页具有指向“族项目”和“子族项目”页面的链接
  • 每个族和子族页面都有一个已分页的产品列表
现在我有两个蜘蛛:

  • GeneralSpider获取主页链接并存储它们
  • ItemSpider从每个页面获取元素
我对Scrapy完全是新手,我正在跟随一些教程来实现这一点。我想知道解析函数有多复杂,规则是如何工作的。我的蜘蛛现在看起来像:

通用皮德尔: 项目蜘蛛:
  • 让爬行器跟随url分页的最佳方法是什么
  • 如果分页为JQueryJQuery,这意味着URL中没有GET变量,是否可以遵循分页

  • 我可以在同一个爬行器中使用不同的“规则””来删除页面的不同部分吗?还是最好让蜘蛛专门化,每个蜘蛛专注于一件事

我也在谷歌上搜索过任何与Scrapy有关的书,但似乎还没有一本完成的书,或者至少我找不到一本

  • 有人知道一些即将出版的书是不是很差劲
编辑: 这2个URL适合此示例。在Eroski主页中,您可以获得产品页面的URL

在产品页面中,您有一个已分页的项目列表(Eroski项目):

  • 获取链接的URL:
  • 获取项目的URL:
在Eroski Fruits页面中,项目的分页似乎是JQuery/AJAX,因为向下滚动时会显示更多的项目,有没有办法通过Scrapy获取所有这些项目

哪种方法是使爬行器跟随url分页的最佳方法

这是非常特定于站点的,取决于分页的实现方式

如果分页是JQuery,这意味着URL中没有GET变量,那么可以遵循分页吗

这正是您的用例——分页是通过额外的AJAX调用实现的,您可以在Scrapy spider中模拟这些调用

我可以在同一个蜘蛛中使用不同的“规则”来刮取页面的不同部分吗?还是最好让蜘蛛专门化,每个蜘蛛专注于一件事

是的,
CrawlSpider
提供的“规则”机制是一项非常强大的技术-它是高度可配置的-您可以有多个规则,其中一些规则将遵循符合特定标准的特定链接,或者位于页面的特定部分。与拥有多个spider相比,拥有一个具有多个规则的spider应该是首选

说到您的特定用例,以下是您的想法:

  • 制定
    规则
    以遵循主页导航菜单中的类别和子类别-这是
    限制路径
    会有帮助的
  • 在回调中,对于每个类别或子类别
    生成一个
    请求
    ,该请求将模拟打开类别页面时浏览器发送的AJAX请求
  • 在AJAX响应处理程序(回调)中,解析可用项,并为同一类别/子类别生成另一个
    请求,但增加
    page
    GET参数(获取下一页)
示例工作实现:

import re
import urllib

import scrapy
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors import LinkExtractor


class ProductItem(scrapy.Item):
    description = scrapy.Field()
    price = scrapy.Field()


class GrupoeroskiSpider(CrawlSpider):
    name = 'grupoeroski'
    allowed_domains = ['compraonline.grupoeroski.com']
    start_urls = ['http://www.compraonline.grupoeroski.com/supermercado/home.jsp']

    rules = [
        Rule(LinkExtractor(restrict_xpaths='//div[@class="navmenu"]'), callback='parse_categories')
    ]

    def parse_categories(self, response):
        pattern = re.compile(r'/(\d+)\-\w+')
        groups = pattern.findall(response.url)
        params = {'page': 1, 'categoria': groups.pop(0)}

        if groups:
            params['grupo'] = groups.pop(0)
        if groups:
            params['familia'] = groups.pop(0)

        url = 'http://www.compraonline.grupoeroski.com/supermercado/ajax/listProducts.jsp?' + urllib.urlencode(params)
        yield scrapy.Request(url,
                             meta={'params': params},
                             callback=self.parse_products,
                             headers={'X-Requested-With': 'XMLHttpRequest'})

    def parse_products(self, response):
        for product in response.xpath('//div[@class="product_element"]'):
            item = ProductItem()
            item['description'] = product.xpath('.//span[@class="description_1"]/text()').extract()[0]
            item['price'] = product.xpath('.//div[@class="precio_line"]/p/text()').extract()[0]
            yield item

        params = response.meta['params']
        params['page'] += 1

        url = 'http://www.compraonline.grupoeroski.com/supermercado/ajax/listProducts.jsp?' + urllib.urlencode(params)
        yield scrapy.Request(url,
                             meta={'params': params},
                             callback=self.parse_products,
                             headers={'X-Requested-With': 'XMLHttpRequest'})
希望这是一个很好的起点


有人知道一些即将发行的剪贴簿吗

我想不起来有什么特别的


虽然我听说一些出版商计划出版一本关于网络抓取的书,但我不想告诉你。

分享到实际网站的链接会让回答更容易。谢谢。@alecxe我添加了一个编辑,检查两个URL都不使用scrapy,所以我无法具体回答。您可能会找到更多使用标准库的刮取示例,如
httplib
urlib
urlib2
发送查询,以及
BeautifulSoup
解析由此获得的网页内容。快速查看您的水果页面,我发现我可以通过在url中添加
page=2
来获取更多项目,例如
http://www.compraonline.grupoeroski.com/supermercado/ajax/listProducts.jsp?page=2&categoria=2059698&grupo=2059699&familia=2059701
这样您就可以循环直到得到一个空页面(这里是3)@埃特纳:谢谢你的帮助!我想用刮痧试试这个解决方案。我知道我可以使用BeautifulSoup、urllib甚至Selenium,但我想使用spidersNo解决这个问题,我只是想提供一个替代方案,因为目前还没有答案。我还希望看到
页面‌​=n
回答分页问题(复制粘贴我在internet浏览器中提供的url时要小心/code:换行符会弄乱
page=2
(添加了两个字符,因此必须取消))谢谢!这是一个非常有用的答案在详细阅读了所有内容后,我非常非常感谢,您为我节省了大量挖掘信息的时间。你的解释太棒了!我欠你一大笔钱!
class GeneralSpider(CrawlSpider):

    name = 'domain'
    allowed_domains = ['domain.org']
    f = open("urls.txt")
    start_urls = [url.strip() for url in f.readlines()]
    # Each URL in the file has pagination if it has more than 30 elements
    # I don't know how to paginate over each URL
    f.close()

    def parse(self, response):
        item = ShopItem()
        item['name'] = response.xpath("//h1[@id='u_name']").extract()
        item['description'] = response.xpath("//h3[@id='desc_item']").extract()
        item['prize'] = response.xpath("//div[@id='price_eur']").extract()
        return item
import re
import urllib

import scrapy
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors import LinkExtractor


class ProductItem(scrapy.Item):
    description = scrapy.Field()
    price = scrapy.Field()


class GrupoeroskiSpider(CrawlSpider):
    name = 'grupoeroski'
    allowed_domains = ['compraonline.grupoeroski.com']
    start_urls = ['http://www.compraonline.grupoeroski.com/supermercado/home.jsp']

    rules = [
        Rule(LinkExtractor(restrict_xpaths='//div[@class="navmenu"]'), callback='parse_categories')
    ]

    def parse_categories(self, response):
        pattern = re.compile(r'/(\d+)\-\w+')
        groups = pattern.findall(response.url)
        params = {'page': 1, 'categoria': groups.pop(0)}

        if groups:
            params['grupo'] = groups.pop(0)
        if groups:
            params['familia'] = groups.pop(0)

        url = 'http://www.compraonline.grupoeroski.com/supermercado/ajax/listProducts.jsp?' + urllib.urlencode(params)
        yield scrapy.Request(url,
                             meta={'params': params},
                             callback=self.parse_products,
                             headers={'X-Requested-With': 'XMLHttpRequest'})

    def parse_products(self, response):
        for product in response.xpath('//div[@class="product_element"]'):
            item = ProductItem()
            item['description'] = product.xpath('.//span[@class="description_1"]/text()').extract()[0]
            item['price'] = product.xpath('.//div[@class="precio_line"]/p/text()').extract()[0]
            yield item

        params = response.meta['params']
        params['page'] += 1

        url = 'http://www.compraonline.grupoeroski.com/supermercado/ajax/listProducts.jsp?' + urllib.urlencode(params)
        yield scrapy.Request(url,
                             meta={'params': params},
                             callback=self.parse_products,
                             headers={'X-Requested-With': 'XMLHttpRequest'})