Scrapy请求主体dict为字节字符串

k2arahey  于 2022-11-09  发布在  其他
关注(0)|答案(1)|浏览(162)

我有一个不完整的start_request函数,我想发送带有body的请求。当我从curl中复制它时,我得到了字符串形式的body,我可以将其作为body传递。
yield scrapy.http.Request(url=url, headers=headers, body=body, method="POST")那样发送它就可以了。
然而,为了进一步的调整,我想把它作为dict data,这样我就可以改变一些变量。
当我以yield scrapy.http.Request(url=url, headers=headers, body=json.dumps(data), method="POST")的形式发送它时,它不工作。我尝试了encode,但没有成功。是发送请求还是解析函数有问题?下面是完整的代码。

def start_requests(self):
    url = 'https://www.tradeinn.com/index.php?action=get_info_elastic_listado&id_tienda=10&idioma=eng'

    headers = {
    "authority": "www.tradeinn.com",
    "accept": "application/json, text/javascript, */*; q=0.01",
    "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
    "origin": "https://www.tradeinn.com",
    "referer": "https://www.tradeinn.com/runnerinn/en/mens-shoes-trail-running-shoes/10005/s",
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36",
    "x-requested-with": "XMLHttpRequest"
}

   body = 'vars%5B%5D=id_familia%3D10002&vars%5B%5D=atributos_e%3D5091%2C6017&vars%5B%5D=model.eng%3Bmodel.eng%3Bvideo_mp4%3Bid_marca%3Bprecio_tachado%3Bsostenible%3Bproductes.talla2%3Bproductes.talla_usa%3Bproductes.talla_jp%3Bproductes.talla_uk%3Btres_sesenta%3Batributos_padre.atributos.id_atribut_valor%3Bproductes.v360%3Bproductes.v180%3Bproductes.v90%3Bproductes.v30%3Bproductes.exist%3Bproductes.stock_reservat%3Bproductes.pmp%3Bproductes.id_producte%3Bproductes.color%3Bproductes.referencia%3Bproductes.brut%3Bproductes.desc_brand%3Bimage_created%3Bid_modelo%3Bfamilias.eng%3Bfamilias.eng%3Bfamilias.id_familia%3Bfamilias.subfamilias.eng%3Bfamilias.subfamilias.eng%3Bfamilias.subfamilias.id_tienda%3Bfamilias.subfamilias.id_subfamilia%3Bproductes.talla%3Bproductes.baja%3Bproductes.rec%3Bprecio_win_209%3Bproductes.sellers.id_seller%3Bproductes.sellers.precios_paises.precio%3Bproductes.sellers.precios_paises.id_pais%3Bfecha_descatalogado%3Bmarca%3Bproductes.talla_uk&vars%5B%5D=v30_sum%3Bdesc%40tm10%3Basc&vars%5B%5D=48&vars%5B%5D=productos&vars%5B%5D=search&vars%5B%5D=id_subfamilia%3D10005&vars%5B%5D=96&texto_search='
   data = {
    'vars[]': [
        'id_familia=10002',
        'atributos_e=5091,6017',
        'model.eng;model.eng;video_mp4;id_marca;precio_tachado;sostenible;productes.talla2;productes.talla_usa;productes.talla_jp;productes.talla_uk;tres_sesenta;atributos_padre.atributos.id_atribut_valor;productes.v360;productes.v180;productes.v90;productes.v30;productes.exist;productes.stock_reservat;productes.pmp;productes.id_producte;productes.color;productes.referencia;productes.brut;productes.desc_brand;image_created;id_modelo;familias.eng;familias.eng;familias.id_familia;familias.subfamilias.eng;familias.subfamilias.eng;familias.subfamilias.id_tienda;familias.subfamilias.id_subfamilia;productes.talla;productes.baja;productes.rec;precio_win_209;productes.sellers.id_seller;productes.sellers.precios_paises.precio;productes.sellers.precios_paises.id_pais;fecha_descatalogado;marca;productes.talla_uk',
        'v30_sum;desc@tm10;asc',
        '48',
        'productos',
        'search',
        'id_subfamilia=10005',
        '96',
    ],
    'texto_search': '',
}

    yield scrapy.http.Request(url=url, headers=headers, body=body, method="POST")

def parse(self, response):
    data = json.loads(response.body)
    yield from data["id_modelos"]
oxf4rvwz

oxf4rvwz1#

使用json不会收到与percent-encoded字符串相同的响应,原因是服务器接受的是percent-encoded字符串,并且知道如何进行转换。
使用python的urllib.parse模块可以很容易地将百分号编码的字符串转换成字典,然后再转换回来。
例如:

from urllib.parse import urlencode, parse_qs

body = 'vars%5B%5D=id_familia%3D10002&vars%5B%5D=atributos_e%3D5091%2C6017&vars%5B%5D=model.eng%3Bmodel.eng%3Bvideo_mp4%3Bid_marca%3Bprecio_tachado%3Bsostenible%3Bproductes.talla2%3Bproductes.talla_usa%3Bproductes.talla_jp%3Bproductes.talla_uk%3Btres_sesenta%3Batributos_padre.atributos.id_atribut_valor%3Bproductes.v360%3Bproductes.v180%3Bproductes.v90%3Bproductes.v30%3Bproductes.exist%3Bproductes.stock_reservat%3Bproductes.pmp%3Bproductes.id_producte%3Bproductes.color%3Bproductes.referencia%3Bproductes.brut%3Bproductes.desc_brand%3Bimage_created%3Bid_modelo%3Bfamilias.eng%3Bfamilias.eng%3Bfamilias.id_familia%3Bfamilias.subfamilias.eng%3Bfamilias.subfamilias.eng%3Bfamilias.subfamilias.id_tienda%3Bfamilias.subfamilias.id_subfamilia%3Bproductes.talla%3Bproductes.baja%3Bproductes.rec%3Bprecio_win_209%3Bproductes.sellers.id_seller%3Bproductes.sellers.precios_paises.precio%3Bproductes.sellers.precios_paises.id_pais%3Bfecha_descatalogado%3Bmarca%3Bproductes.talla_uk&vars%5B%5D=v30_sum%3Bdesc%40tm10%3Basc&vars%5B%5D=48&vars%5B%5D=productos&vars%5B%5D=search&vars%5B%5D=id_subfamilia%3D10005&vars%5B%5D=96&texto_search='
data = parse_qs(body)  # <-- this gives you a dict
print(data, "\n\n") 

# make some changes to the dictionary

body = urlencode(data, doseq=True)  # <--- converts to percent-encoded string
print(body)

输出:

{'vars[]': ['id_familia=10002', 'atributos_e=5091,6017', 'model.eng;model.eng;video_mp4;id_marca;precio_tachado;sostenible;productes.talla2;productes.talla_usa;productes.talla_jp;productes.talla_uk;tres_s
esenta;atributos_padre.atributos.id_atribut_valor;productes.v360;productes.v180;productes.v90;productes.v30;productes.exist;productes.stock_reservat;productes.pmp;productes.id_producte;productes.color;pro
ductes.referencia;productes.brut;productes.desc_brand;image_created;id_modelo;familias.eng;familias.eng;familias.id_familia;familias.subfamilias.eng;familias.subfamilias.eng;familias.subfamilias.id_tienda
;familias.subfamilias.id_subfamilia;productes.talla;productes.baja;productes.rec;precio_win_209;productes.sellers.id_seller;productes.sellers.precios_paises.precio;productes.sellers.precios_paises.id_pais
;fecha_descatalogado;marca;productes.talla_uk', 'v30_sum;desc@tm10;asc', '48', 'productos', 'search', 'id_subfamilia=10005', '96']}

vars%5B%5D=id_familia%3D10002&vars%5B%5D=atributos_e%3D5091%2C6017&vars%5B%5D=model.eng%3Bmodel.eng%3Bvideo_mp4%3Bid_marca%3Bprecio_tachado%3Bsostenible%3Bproductes.talla2%3Bproductes.talla_usa%3Bproducte
s.talla_jp%3Bproductes.talla_uk%3Btres_sesenta%3Batributos_padre.atributos.id_atribut_valor%3Bproductes.v360%3Bproductes.v180%3Bproductes.v90%3Bproductes.v30%3Bproductes.exist%3Bproductes.stock_reservat%3
Bproductes.pmp%3Bproductes.id_producte%3Bproductes.color%3Bproductes.referencia%3Bproductes.brut%3Bproductes.desc_brand%3Bimage_created%3Bid_modelo%3Bfamilias.eng%3Bfamilias.eng%3Bfamilias.id_familia%3Bfa
milias.subfamilias.eng%3Bfamilias.subfamilias.eng%3Bfamilias.subfamilias.id_tienda%3Bfamilias.subfamilias.id_subfamilia%3Bproductes.talla%3Bproductes.baja%3Bproductes.rec%3Bprecio_win_209%3Bproductes.sell
ers.id_seller%3Bproductes.sellers.precios_paises.precio%3Bproductes.sellers.precios_paises.id_pais%3Bfecha_descatalogado%3Bmarca%3Bproductes.talla_uk&vars%5B%5D=v30_sum%3Bdesc%40tm10%3Basc&vars%5B%5D=48&v
ars%5B%5D=productos&vars%5B%5D=search&vars%5B%5D=id_subfamilia%3D10005&vars%5B%5D=96

对于您的示例,一旦您对data dict进行了所需的更改,您只需将dict转换回正确的格式,并将其作为参数提交给请求对象。
例如:

from urllib.parse import urlencode
...
...

yield scrapy.http.Request(url=url, headers=headers, body=urlencode(data, doseq=True), method="POST")

相关问题