Scrapy-从多个页面提取数据

时间:2020-02-13 22:28:06

标签: python-3.x url scrapy

class HomedepotcrawlSpider(scrapy.Spider):
      name = 'homeDepotCrawl'
      allowed_domains = ['homedepot.com']
      start_urls = ['https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=0']

def parse(self, response):

    #call home depot function
    for item in self.parseHomeDepot(response):
        yield item

    nextPageSelect = '.hd-pagination__link'
    next_page = response.css(nextPageSelect).getall()
    if next_page:
        yield scrapy.Request(
            response.urljoin(next_page),
            callback=self.parse
        )

编辑-

.hd-pagination__link的获取方式是使用Google Chrome的CSS选择器扩展名,然后选择了下一页图标(附有屏幕截图)

Screenshot of css for next page

所以我尝试了一些事情,这对我来说是最有意义的方式,我认为我只是为下一页抓住了错误的对象。截至目前,我的程序仅从第一页获取数据,似乎遍历页面的代码块已被忽略。

我发现了一个带有URL的模式,其中页码以24为增量表示(也许是由于项目编号?)。例如:

第1页:https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=0

第2页:https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=24

第3页:https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=48 。 。 。 。 。 。

第n页:https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=[(n * 24)-24]

ect。

当我尝试测试与页码相关的代码[在Na0 = x后递增编号]时,我只会遍历第一页x次。 (我的输出将是第一页(24个项目)重复x次。

我也研究了爬虫,但并不能真正理解它/实现。

对我的代码/其他方法的任何帮助将不胜感激!

这也不是我的整个程序,我保留了parseHomeDepot函数,因为我认为这不是必需的,但是如果需要代码,请告诉我!

3 个答案:

答案 0 :(得分:4)

在我看来,您遇到了几个问题。

首先,您可能会得到包含下一页链接的整个html元素,而您正在寻找的只是链接。所以我建议您像这样使用css选择器:

nextPageSelect = '.hd-pagination__link::attr(href)'

这将为您提供链接,而不是整个HTML元素。我建议进一步研究CSS选择器here

第二,从逻辑上讲,您的代码似乎有问题。

next_page = response.css(nextPageSelect).getall()

这段代码为您提供了当前页面上所有“下一页”链接的列表,但是您将整个列表视为一个链接。我建议使用for循环。像这样:

   if next_pages:
    for page in next_pages:
        yield scrapy.Request(
            response.urljoin(page),
            callback=self.parse
        )

现在,我想更好地利用Scrapy的并行和并发功能,您可能想返回一个“ scrapy.Requests”列表,而不是对找到的每个请求都进行yield。总结一下:

nextPageSelect = '.hd-pagination__link::attr(href)'
next_pages = response.css(nextPageSelect).getall()
requests = []
if next_pages:
    for page in next_pages:
        requests.append(scrapy.Request(
            response.urljoin(page),
            callback=self.parse
        ))
return requests

祝你好运!

答案 1 :(得分:2)

以下是您要执行的操作代码:

import scrapy
from urllib.parse import urlsplit, urljoin

class HomedepotSpider(scrapy.Spider):
    name = 'homedepot'
    start_urls = ['https://www.homedepot.com/b/N-5yc1v/Ntk-ProductInfoMatch/Ntt-zline?NCNI-5&experienceName=default&Nao=0']

    def parse(self, response):

        # Here you do something with your items

        next_page = response.css('a.hd-pagination__link[title=Next]::attr(href)').get()
        if next_page is not None:
            o = urlsplit(response.url)
            base_url = f'{o.scheme}://{o.netloc}'
            next_page_url = urljoin(base_url,next_page)
            yield response.follow(next_page_url, callback=self.parse)

在此代码中,我要指出的主要内容是:

  1. 检查选择器是否进入下一页。它检查属性标题,并且仅选择标题为“ Next”的元素。那就是识别分页中的最后一个按钮。我不确定您的示例是否确定了右键按钮
  2. 您获得的下一页是相对网址。这样做是使用urljoin获取当前url(response.url)的基础部分,然后使用urljoin附加此亲戚
  3. 一旦有了下一页的网址,您就可以使用response.follow指示蜘蛛程序将具有所选回调的网址添加到要抓取的网址列表中

这也是显示其已爬网31页的拼凑日志。这是执行后应该得到的东西

2020-02-21 10:42:04 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 44799,
 'downloader/request_count': 31,
 'downloader/request_method_count/GET': 31,
 'downloader/response_bytes': 1875031,
 'downloader/response_count': 31,
 'downloader/response_status_count/200': 31,
 'dupefilter/filtered': 1,
 'elapsed_time_seconds': 13.690273,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2020, 2, 21, 10, 42, 4, 145686),
 'log_count/DEBUG': 32,
 'log_count/INFO': 10,
 'memusage/max': 52195328,
 'memusage/startup': 52195328,
 'request_depth_max': 31,
 'response_received_count': 31,
 'scheduler/dequeued': 31,
 'scheduler/dequeued/memory': 31,
 'scheduler/enqueued': 31,
 'scheduler/enqueued/memory': 31,
 'start_time': datetime.datetime(2020, 2, 21, 10, 41, 50, 455413)}
2020-02-21 10:42:04 [scrapy.core.engine] INFO: Spider closed (finished)

我希望这会有所帮助!

答案 2 :(得分:1)

尝试这种方法:

获取当前页码并将其用作参考,获取下一页的编号,然后在与计数器相乘后在url中使用

try:
    nextpage_number = response.xpath("//ul[contains(@class,'hd-pagination')]/li/a[contains(@class,'active ')]/ancestor::li[1]/following-sibling::li[1]/a/@title")[0].extract()
    current_url_stip = re.search( r"(.+Nao=)\d+", response.url)
    new_url = "%s=%s" % ( current_url_stip.group(1), nextpage_number * 24 )
    yield scrapy.Request(new_url, meta=response.meta)
except:
    pass