【问题标题】:scrapy+selenium how to crawl a different page list once i'm done with one?scrapy+selenium 完成后如何抓取不同的页面列表?
【发布时间】:2020-09-03 11:18:20
【问题描述】:

我正在尝试从“动作/用户交易”网站上抓取数据,它是意大利语的,所以我会尽量做到清楚。 我对 Python 和 Scrapy 也很陌生,这是我的第一个项目。 该网站没有一个简单的方法来跟踪链接,所以我不得不想出一些东西。 首先,我转到列出所有页面的总列表,这很容易,因为第一页是“https://www.subito.it/annunci-italia/vendita/usato/?o=1”在“/?o=218776”上,我选择页面的第一个链接并用 selenium 打开它,一旦在这里我得到我需要的数据并单击“下一页”按钮,但这是棘手的部分。 如果我使用相同的 URL 转到同一页面,则没有“下一页”按钮,它仅在您位于列表页面的第一个时才有效,然后单击页面链接,从这里您现在可以关注另一个链接。 我以为它会完成,但我错了。一般列表分为页面(.../?o=1,.../?o=2 等),每个页面都有 X 个链接(我没有算过),当你在拍卖页面之一(来自列表页面,因此您可以使用“下一页”按钮),然后单击“下一页”,您按照一般列表中的链接顺序进行操作。 更清楚的是,如果总列表有20万页,每页有50个链接,当你点击页面的第一个链接时,你可以点击“下一页”49次,之后“下一页”按钮无效并且您不能转到旧链接,您必须返回列表并转到下一页,然后重复该过程。

import scrapy
from scrapy.http import HtmlResponse

from scrapy.selector import Selector

from selenium import webdriver

class NumeriSpider(scrapy.Spider):
name = "quotes"
start_urls = [
    'https://www.subito.it/annunci-italia/vendita/usato/?o=41',
]
    
def __init__(self):
    self.driver = webdriver.Firefox()

def parse(self, response):
    self.driver.get(response.url)
    self.driver.find_element_by_xpath('/html/body/div[5]/div/main/div[2]/div[5]/div[2]/div[1]/div[3]/div[1]/a').click()
    while True:
        sel = Selector(text=self.driver.page_source)
        item = {
            'titolo': sel.xpath('//h1[@class= "classes_sbt-text-atom__2GBat classes_token-h4__3_Swu size-normal classes_weight-semibold__1RkLc ad-info__title"]/text()').get(),
            'nome': sel.xpath("//p[@class='classes_sbt-text-atom__2GBat classes_token-subheading__3yij_ size-normal classes_weight-semibold__1RkLc user-name jsx-1261801758']/text()").get(),
            'luogo': sel.xpath("//span[@class='classes_sbt-text-atom__2GBat classes_token-overline__2P5H8 size-normal ad-info__location__text']/text()").get()
            }
        yield item
        next = self.driver.find_element_by_xpath('/html/body/div[5]/div/main/div[2]/div[1]/section[1]/nav/div/div/button[2]')
        try:
            next.click()
        except:
            driver.quit()

这是我在 scrapy 文档和许多网站/stackoverflow 页面的帮助下编写的代码。 我给它一般列表的页面来抓取,在这种情况下https://www.subito.it/annunci-italia/vendita/usato/?o=41,它找到页面的第一个链接(self.driver.find_element_by_xpath('/html/body/div[5]/div/main/div[2]/div[5]/div[2]/div[1]/div[3]/div[1]/a').click())然后开始获取我想要的数据。完成后,它会单击“下一页”按钮 (next = self.driver.find_element_by_xpath('/html/body/div[5]/div/main/div[2]/div[1]/section[1]/nav/div/div/button[2]')) 并重复“获取数据-单击下一页”过程。 最后一个项目页面将有一个非活动的“下一页”按钮,所以在爬虫卡住的那一刻,我手动关闭浏览器,用记事本++编辑“start_urls”链接成为我刚刚抓取的页面之后的页面,然后再次运行爬虫来抓取这个页面。

我希望它是全自动的,所以我可以让它在几个小时内完成它的工作(我将数据保存在一个 json 文件 atm 中)。

“非活动”下一页按钮与活动按钮的不同之处仅在于 disabled="" 属性,我如何检测到这一点?一旦检测到,我如何告诉爬虫返回列表页面加 1 并再次执行数据抓取过程? 我的问题只是检测到该非活动按钮并创建一个循环,将 1 添加到我提供的列表页面(如果我从链接“https://www.subito.it/annunci-italia/vendita/usato/?o=1”开始,它应该转到“https://www.subito.it/annunci-italia/vendita/usato/?o=2”并做同样的事情)

【问题讨论】:

  • 好的,我得到了检测按钮是否处于活动状态的部分 isExists = sel.xpath('/html/body/div[5]/div/main/div[2]/div[ 1]/section[1]/nav/div/div/button[2]/@disabled') 如果不是 isExists: next.click() else: self.driver.quit()

标签: python selenium scrapy web-crawler


【解决方案1】:

可以通过覆盖start_requests 方法来迭代页面。为了达到目的,您需要编写一个循环来请求所有(在本例中为 219xxx)页面并提取第二层页面hrefs。

def start_requests(self):
     pages_count = 1 # in this method you need to hard code your pages quantity
     for i in range(pages_count)
          url = 'https://www.subito.it/annunci-italia/vendita/usato/?o=%s' % str(i + 1)
          scrapy.Request(url, callback=self.parse)

或者以更好的方式找出第一层有多少页,第一层总是在最后一个class="unselected-page"元素中,这样你就可以用response.xpath('//*[@class="unselected-page"]//text()').getall()[-1] 找到它。在这种情况下,您需要在第一个 parse 方法中请求第一层页面。

def start_requests(self):
     base_url = 'https://www.subito.it/annunci-italia/vendita/usato'
     scrapy.Request(base_url, callback=self.parse_first_layer)

def parse_first_layer(self, response):
     pages_count = int(response.xpath('//*[@class="unselected-page"]//text()').getall()[-1])
     for i in range(pages_count)
          url = 'https://www.subito.it/annunci-italia/vendita/usato/?o=%s' % str(i + 1)
          scrapy.Request(url, callback=self.parse_second_layer)

到达第一层链接后,您可以像以前一样在每个页面中迭代 50 多个链接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 2016-03-16
    • 2012-10-26
    相关资源
    最近更新 更多