使用Scrapy从带有规则的URL列表中使用参数进行爬网

时间:2016-12-29 10:42:20

标签: python python-3.x web-scraping scrapy scrapy-spider

我是Scrapy和Python的新手。我想做以下事情:

  1. 访问网址并获取所有链接包含" shop / products" 作为网址的一部分。链接如下所示:" http://www.example.com/shop/products/category-name"

  2. 废弃start_urls的网址并获取总产品数量 TOTAL 。在代码上TOTAL = num_items_per_category

  3. 最后,将&#34;?sort = Top&amp; size = 12&amp; start = PARAM &#34; 添加到网址。 PARAM <= TOTAL时,PARAM必须在每次迭代时递增12。最终的网址是&#34; http://www.example.com/shop/products/category-name?sort=Top&size=12&start=PARAM&#34;

  4. 从生成的start_urls中获取另一个url并再次启动第2步。

  5. 这是我的蜘蛛代码:

    import scrapy
    import re
    import datetime
    
    from scrapy.spiders import CrawlSpider, Rule
    from scrapy.linkextractors.lxmlhtml import LxmlLinkExtractor
    from scrapy.http.request import Request
    
    class MySpider(CrawlSpider):
        name = 'my_spider'
        allowed_domains = ['example.com']
        start_urls = ['http://www.example.com/shop/products']
        rules = (
            Rule(LxmlLinkExtractor(
                restrict_xpaths=('.//li[@class="item"]/a')),
                follow=False,
                callback='parse_list'
            ),
         )
    
        def parse_list(self, response):
            SET_SELECTOR = '.product'
            for item in response.css(ITEM_SELECTOR):
                NAME_SELECTOR = 'div[@class="product"]/h2/a/@title'
                yield {
                    'name': item.xpath(NAME_SELECTOR).extract_first()
                }
    
            NUM_ITEMS_PER_CATEGORY_SELECTOR = 'div[@id="search"]/@data-count'
            num_items_per_category = item.xpath(NUM_ITEMS_PER_CATEGORY_SELECTOR).extract_first()
            nipc = int(0 if num_items_per_category is None else num_items_per_category)
            try:
                next_start = response.meta["next_start"]
            except KeyError:
                next_start = 0
            if next_start <= nipc:
                yield scrapy.Request(
                    response.urljoin('%s?sort=Top&size=12&start=%s' % (response.url, next_start)),
                    meta={"next_start": next_start + 12},
                    dont_filter=True,
                    callback = self.parse_list
                )
    

    问题是:

    1. 我不知道在规则中是否存在任何css选择器或正则表达式来选择我想要的每个链接。在代码上,我访问了一条路径,我知道有一些我想要的链接,但页面上还有更多内容。

    2. 代码无法正常工作,我期待。似乎 next_start 在每次迭代时都没有递增12。代码只生成生成的start_urls列表中每个url的前12个元素。我正确使用 meta 变量吗?或者我可能需要每个类别页面的另一个第一个废料来获取TOTAL计数,然后才能使用它来迭代它?或者我可能需要使用 start_requests 的另一种方法...你怎么看?

1 个答案:

答案 0 :(得分:0)

您的蜘蛛完全做的是访问网址http://www.example.com/shop/products,提取<li class="item">元素中的所有链接,并使用parse_list回调获取所有链接。我认为这不是您正在等待的行为 - 相反,您应该在规则中使用包含种子URL的一些起始URL和带有allow=r"shop/products"的Extractor。

此部分'%s?sort=Top&size=12&start=%s' % (response.url, next_start)也是错误的,因为response.url包含完整的URL,包括GET参数,因此每次将带有参数的部分追加到现有参数字符串(如?sort=Top&size=12&start=0?sort=Top&size=12&start=12?sort=Top&size=12&start=24)。在添加新字符串之前清除url中的参数或使用FormRequest作为传递参数的更方便的方法。

顺便说一句,Scrapy有非常方便的交互式控制台用于调试目的,您可以使用scrapy.shell.inspect_response从蜘蛛的任何部分调用。