scrapy - 如何模拟按下按钮以继续使用 Scrapy 抓取更多元素
问题描述
在这个页面(https://www.realestate.com.kh/buy/)上,我设法抓取了一个广告列表,并使用以下代码单独解析它们的内容:
import scrapy
class scrapingThings(scrapy.Spider):
name = 'scrapingThings'
# allowed_domains = ['https://www.realestate.com.kh/buy/']
start_urls = ['https://www.realestate.com.kh/buy/']
def parse(self, response):
ads = response.xpath('//*[@class="featured css-ineky e1jqslr40"]//a/@href')
c = 0
for url in ads:
c += 1
absolute_url = response.urljoin(url.extract())
self.item = {}
self.item['url'] = absolute_url
yield scrapy.Request(absolute_url, callback=self.parse_ad, meta={'item': self.item})
def parse_ad(self, response):
# Extract things
yield {
# Yield things
}
但是,我想自动从一个页面切换到另一个页面,以获取所有可用的广告(不仅在第一页上,而且在所有页面上)。我猜,通过模拟按下此屏幕截图中显示的 1、2、3、4、...、50 个按钮:
Scrapy甚至可以做到这一点吗?如果是这样,如何实现这一目标?
解决方案
是的,这是可能的。让我向您展示两种方法:
您可以让您的蜘蛛选择按钮,获取@href
它们的值,构建一个 [完整] URL 并yield
作为新请求。这是一个例子:
def parse(self, response):
....
href = response.xpath('//div[@class="desktop-buttons"]/a[@class="css-owq2hj"]/following-sibling::a[1]/@href').get()
req_url = response.urljoin(href)
yield Request(url=req_url, callback=self.parse_ad)
- 示例中的选择器将始终返回
@href
下一页按钮的 (它只返回一个值,如果您在第 2 页,则返回@href
第 2 页的) - 在这个页面中,href是一个相对的url,所以我们需要使用
response.urljoin()
方法来构建一个完整的url。它将使用响应作为基础。 - 我们
yield
一个新的请求,响应会在你确定的回调函数中解析。 - 这将要求您的回调函数始终产生对下一页的请求。所以这是一个递归解决方案。
一种更简单的方法是仅观察 href 的模式并手动处理yield
所有请求。每个按钮都有一个href,"/buy/?page={nr}"
其中{nr}
是页数,se可以任意更改这个nr值并一次产生所有请求。
def parse(self, response):
....
nr_pages = response.xpath('//div[@class="desktop-buttons"]/a[@class="css-1en2dru"]//text()').getall()
last_page_nr = int(nr_pages[-1])
for nr in range(2, last_page_nr + 1):
req_url = f'/buy/?page={nr}'
yield Request(url=response.urljoin(req_url), callback=self.parse_ad)
nr_pages
返回所有按钮的数量last_page_nr
选择最后一个数字(这是最后一个可用页面)- 我们在 2 到值
last_page_nr
(在这种情况下为 50)之间的范围内循环,并且在每个循环中我们请求一个新页面(对应于数字)。 - 这样,您可以在您的方法中发出所有请求,并在没有递归调用的情况下
parse
解析响应。parse_ad
最后我建议你看一下scrapy教程,它涵盖了几种常见的scraping场景。
推荐阅读
- java - 如何修复 Spring Boot 的 BasicAuth?
- c - 类型俄罗斯方块 - 卡住混合单子和纯代码
- php - Dockerfile 构建 Laravel Telescope 试图连接到 Redis 服务尚未“启动”
- python - 使用元组中的第一个值获取元组中的第二个值
- javascript - Tabulator:删除行时如何修改本地数组?
- javascript - ngx-smart-table 上的本地化
- c# - 子弹不动。统一
- python - 单击指向另一个模板的链接时,Django 模板只会重新加载
- docker - 如何从命令行制作 docker-compose 文件
- python - 说下面的代码在 Python3 中实现了多态是否正确?