相信你做得很好! 我需要您的支持,我正在尝试抓取此网页:https://servicio.mapa.gob.es/regfiweb# 进入后,您必须前往:
我想下载所有pdf文件,但没有带有href属性的节点。相反,有一些带有 data-id 的按钮,通过 javascript 触发来启动 pdf 下载。
我尝试过但完全不成功。
你有什么想法吗?
我想逐页导航并下载每页的 pdf。
我的代码:
import scrapy
class SimpleSpider(scrapy.Spider):
name = "simple"
# allowed_domains = ["x"]
start_urls = ["https://servicio.mapa.gob.es/regfiweb#"]
def parse(self, response):
for book in response.css('.col'):
title = book.css('span ::text').get()
link = response.urljoin(
# book.css('a.pdf ::attr(href)').get()
book.css('a::attr(href)').get()
)
yield {
'Title': title,
'file_urls': [link]
}
如果您打开 devtools 并转到网络选项卡,您可以看到“产品”页面的 url。您可以前往此处,填写表格并提交。
如果您停留在页面上并点击搜索按钮,您可以看到页面如何请求结果。我发现这更容易,这就是我要做的。你可以看到最后的数字,对我来说它看起来像 unix 时间戳。
如果我们检查 pdf 下载按钮,我们会看到:
function(n) {
n.stopImmediatePropagation();
n.stopPropagation();
n.preventDefault();
var i = $("#exportFichaProductoPdf").val(),
t = {};
t.idProducto = parseInt(this.dataset.id);
exportPdf(i, t)
}
查找
exportPdf
函数后,您会发现:
exportPdf = function (n, t) {
$.ajax({
url: n,
data: { dataDto: t },
type: 'POST',
xhrFields: { responseType: 'blob' },
success: function (n, t, i) {
var s, u;
console.log(n);
var e = new Blob([n], { type: 'application/pdf' }), r = document.createElement('a'), o = '', f = i.getResponseHeader('Content-Disposition');
f && f.indexOf('attachment') !== -1 && (s = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/, u = s.exec(f), u != null && u[1] && (o = u[1].replace(/['"]/g, '')));
/^((?!chrome|android).)*safari/i.test(navigator.userAgent) ? window.open(window.URL.createObjectURL(e), '_blank') : (r.href = window.URL.createObjectURL(e), r.target = '_blank', r.download = o, document.body.appendChild(r), r.click());
},
beforeSend: function () {
$('#loadingDiv').show();
},
complete: function () {
$('#loadingDiv').hide();
},
error: function (n) {
console.log(n.status);
console.log(n.responseText);
var t = document.createElement('div');
t.innerHTML = 'En este momentos el documento no está disponible, estamos trabajando para que pueda obtenerlo lo antes posible.';
swal({
title: 'Documento no disponible',
content: t,
icon: 'warning'
});
}
});
}
所以基本上我们需要一个 url 和 id,以便我们可以重新创建请求:
import scrapy
import os
import time
def get_timestamp_ms():
return int(time.time() * 1000)
class SimpleSpider(scrapy.Spider):
name = "simple"
allowed_domains = ["servicio.mapa.gob.es"]
base_url = "https://servicio.mapa.gob.es/regfiweb/Productos/ProductosGrid?NombreComercial=&Titular=&NumRegistro=&Fabricante=&IdSustancia=-1&IdEstado=1&IdAmbito=undefined&IdPlaga=-1&IdFuncion=-1&IdCultivo=-1&IdSistemaCultivo=-1&IdTipoUsuario=-1&AncestrosCultivos=false&AncestrosPlagas=false&FecRenoDesde=&FecRenoHasta=&FecCaduDesde=&FecCaduHasta=&FecModiDesde=&FecModiHasta=&FecInscDesde=&FecInscHasta=&FecLimiDesde=&FecLimiHasta=&productosGrid-page={}&_={}"
base_dir = "downloads"
def start_requests(self):
page = 1
yield scrapy.Request(url=self.base_url.format(str(page), str(get_timestamp_ms())), cb_kwargs={'page': page})
def parse(self, response, page):
from scrapy.shell import open_in_browser
open_in_browser(response)
for book in response.xpath('//tr[not(ancestor::thead)]'):
title = book.xpath('./td[5]//text()').get(default="")
file_id = book.xpath('./td[last()]/button/@data-id').get()
if file_id:
yield scrapy.FormRequest(url="https://servicio.mapa.gob.es/regfiweb/Productos/ExportFichaProductoPdf", formdata={"idProducto": file_id}, method="POST", cb_kwargs={"title": f"{title}_{file_id}"}, callback=self.download_pdf, dont_filter=True)
# pagination
page += 1
num_pages = response.xpath('//button[@data-page][last()]/@data-page').get(default=0)
if page < int(num_pages):
yield scrapy.Request(url=self.base_url.format(str(page), str(get_timestamp_ms())), cb_kwargs={'page': page})
def download_pdf(self, response, title):
filename = os.path.join(self.base_dir, title+".pdf")
with open(filename, 'wb') as f:
f.write(response.body)
在运行代码之前,您需要确保
base_dir
存在。
这只是一个示例,您可能需要添加分页和搜索查询。