Fetch product category matching the product ID - scrapy
I have created a keywords.csv file in my resource folder in order to automatically fetch the data from all the products listed in there. This works perfectly. The first column of the .csv-file is named "keywords". The keywords are based on a unique number representing the product category (i.e., high pressure washer, floor cleaner, ...). I am using this number to adjust the API URL where I am fetching all the data from.
I would like to print out the product category. Because there is no product category defined in the API where I am fetching the data from, I would like to print out the second column of my .csv-file, being "keywordtype". The "keywordtype" should be printed to the products with the same "keyword".
Secondly, I've been googling around but couldn't find a solution for replacing multiple characters in one string. Is there a way of making some sort of dictionairy so that "\u00e9" gets replaced with "é", "\u00b2" with "²", etc. I tried using .replace('text','') and .split(), but for multiple characters this isn't sufficient.
What I tried
I tried calling the "keywordtype" in the def parse(self, response):, but I don't know how to make it check which keyword is being used. Therefore it keeps printing the same "keywordtype" over and over again.
...
def parse(self, response):
#Calling the "category" from the keywords.csv file -- THIS IS NOT WORKING
with open(os.path.join(os.path.dirname(__file__), "../resources/keywords.csv")) as search_keywords:
for keyword in csv.DictReader(search_keywords):
category=keyword["keywordtype"]
...
FULL CODE #1
Spider.py
# -*- coding: utf-8 -*-
"""
Created on Mon Aug 12 22:44:35 2019
#author: bergs
"""
# -*- coding: utf-8 -*-
import scrapy
from krc.items import KrcItem
import json
import os
import csv
import time
import datetime
class KRCSpider(scrapy.Spider):
name = "krc_spider"
allowed_domains = ["kaercher.com"]
start_urls = ['https://www.kaercher.com/api/v1/products/search/shoppableproducts/partial/20035386?page=1&size=8&isocode=nl-NL']
def start_requests(self):
"""Read keywords from keywords file amd construct the search URL"""
with open(os.path.join(os.path.dirname(__file__), "../resources/keywords.csv")) as search_keywords:
for keyword in csv.DictReader(search_keywords):
search_text=keyword["keyword"]
category = keyword["keywordtype"]
url="https://www.kaercher.com/api/v1/products/search/shoppableproducts/partial/{0}?page=1&size=8&isocode=nl-NL".format(
search_text)
# The meta is used to send our search text into the parser as metadata
yield scrapy.Request(url, callback = self.parse, meta = {"search_text": search_text, "category": category})
def parse(self, response):
category = response.meta["category"]
current_page = response.meta.get("page", 1)
next_page = current_page + 1
#Printing the timestamp when fetching the data, using default timezone from the requesting machine
ts = time.time()
timestamp = datetime.datetime.fromtimestamp(ts).strftime('%d-%m-%Y %H:%M:%S')
#Defining the items
item = KrcItem()
data = json.loads(response.text)
for company in data.get('products', []):
item["productid"] = company["id"]
item["category"] = category
item["name"] = company["name"]
item["description"] = company["description"]
item["price"] = company["priceFormatted"].replace("\u20ac","").strip()
item["timestamp"] = timestamp
yield item
#Checking whether "isTruncated" is true (boolean), if so, next page will be triggered
if data["isTruncated"]:
yield scrapy.Request(
url="https://www.kaercher.com/api/v1/products/search/shoppableproducts/partial/20035386?page={page}&size=8&isocode=nl-NL".format(page=next_page),
callback=self.parse,
meta={'page': next_page},
)
FULL CODE #2
# -*- coding: utf-8 -*-
"""
Created on Mon Aug 12 22:44:35 2019
#author: bergs
"""
# -*- coding: utf-8 -*-
import scrapy
from krc.items import KrcItem
import json
import os
import csv
import time
import datetime
class KRCSpider(scrapy.Spider):
name = "krc_spider"
allowed_domains = ["kaercher.com"]
start_urls = ['https://www.kaercher.com/api/v1/products/search/shoppableproducts/partial/20035386?page=1&size=8&isocode=nl-NL']
def start_requests(self):
"""Read keywords from keywords file amd construct the search URL"""
with open(os.path.join(os.path.dirname(__file__), "../resources/keywords.csv")) as search_keywords:
for keyword in csv.DictReader(search_keywords):
search_text = keyword["keyword"]
url="https://www.kaercher.com/api/v1/products/search/shoppableproducts/partial/{0}?page=1&size=8&isocode=nl-NL".format(
search_text)
# The meta is used to send our search text into the parser as metadata
yield scrapy.Request(url, callback = self.parse, meta = {"search_text": search_text})
def parse(self, response):
current_page = response.meta.get("page", 1)
next_page = current_page + 1
#Printing the timestamp when fetching the data, using default timezone from the requesting machine
ts = time.time()
timestamp = datetime.datetime.fromtimestamp(ts).strftime('%d-%m-%Y %H:%M:%S')
#Defining the items
item = KrcItem()
data = json.loads(response.text)
for company in data.get('products', []):
item["productid"] = company["id"]
item["category"] = company["url"].split('/')[-2].replace('-',' ')
item["name"] = company["name"]
item["description"] = company["description"]
item["price"] = company["priceFormatted"].replace("\u20ac","").strip()
item["timestamp"] = timestamp
yield item
#Checking whether "isTruncated" is true (boolean), if so, next page will be triggered
if data["isTruncated"]:
yield scrapy.Request(
url="https://www.kaercher.com/api/v1/products/search/shoppableproducts/partial/20035386?page={page}&size=8&isocode=nl-NL".format(page=next_page),
callback=self.parse,
meta={'page': next_page},
)
Keywords.csv
keyword,keywordtype
20035386,Hogedrukreiniger
20035424,Window Vacs
items.py
import scrapy
class KrcItem(scrapy.Item):
productid=scrapy.Field()
name=scrapy.Field()
description=scrapy.Field()
price=scrapy.Field()
producttype=scrapy.Field()
timestamp=scrapy.Field()
category=scrapy.Field()
pass
Results.json #1
[
{"productid": 10491477, "category": "Window Vacs", "name": "WV 6 + KV 4(wit)", "description": "De vibrerende accu-wisser KV 4 inclusief elektrische bevochtiging, vibratie, tweede wisdoek en meer accessoires maakt het vuil los - en de Window Vac WV 6 zuigt het achterblijvende water af.", "price": "169,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10491478, "category": "Window Vacs", "name": "WV 6 + KV 4", "description": "Schone vensters in een handomdraai: met de vibrerende Window Vac KV 4 inclusief elektrische watervoorziening en vibratie maakt u het vuil eerst los en daarna zuigt u met de Window Vac WV 6 het vuile water af.", "price": "159,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10491479, "category": "Window Vacs", "name": "WV 6 Plus (wit)", "description": "In een set met 2 wisdoeken voor binnen en buiten, sproeiflacon, reinigingsmiddel en vuilkrabber: de Window Vac WV 6 Premium met innovatieve zuigstrip is nog flexibeler in gebruik.", "price": "109,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10491480, "category": "Window Vacs", "name": "WV 6 Plus", "description": "Met innovatieve striptechnologie en nog flexibeler in gebruik: de Window Vac WV 6 Plus voor streepvrij schone vensters in een mum van tijd.", "price": "99,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10491481, "category": "Window Vacs", "name": "WV 2 + KV4 (wit)", "description": "Sterk duo voor streepvrij schone vensters: de vibrerende accu-wisser KV 4 inclusief elektrische bevochtiging, vibratie, tweede wisdoek en meer extra's, en de Window Vac WV 2.", "price": "139,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10491482, "category": "Window Vacs", "name": "WV 2 + KV 4", "description": "Voor moeiteloos ramen lappen: de vibrerende accu-wisser KV 4 inclusief elektrische watervoorziening en trilfunctie maakt het vuil los - en de Window Vac WV 2 zuigt het vuile water af.", "price": "129,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10475755, "category": "Window Vacs", "name": "KV 4 Premium", "description": "Inclusief tweede wisdoek: de Window Vac KV 4 met elektrische watervoorziening en ondersteunende trilfunctie maakt het vuil moeiteloos los van alle gladde oppervlakken.", "price": "89,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10475756, "category": "Window Vacs", "name": "KV 4", "description": "De vibrerende accu-wisser KV 4 maakt vuil moeiteloos los van gladde oppervlakken. Door het elektrisch aangebrachte water en de trillingen wordt handmatig schrobben overbodig.", "price": "79,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10461927, "category": "Hogedrukreiniger", "name": "K 7 Premium Full Control Plus Home", "description": "Inclusief slanghaspel en Home Kit: de K 7 Premium Full Control Plus Home. U kunt de juiste druk instellen met de +/- knoppen en de LCD-scherm op het hogedrukpistool van de hogedrukreiniger.", "price": "699,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10453128, "category": "Hogedrukreiniger", "name": "K 7 Premium Full Control Plus", "description": "Inclusief slanghaspel: de K 7 Premium Full Control Plus. U kunt de juiste druk instellen met de +/- knoppen en het LCD-scherm op het hogedrukpistool van de hogedrukreiniger.", "price": "639,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10461929, "category": "Hogedrukreiniger", "name": "K 7 Full Control Plus Home", "description": "De ideale hogedrukreiniger voor regelmatig gebruik op hardnekkig vuil. K 7 Full Control Plus Home met Home Kit en hogedrukpistool inclusief +/- knoppen voor drukregeling en LCD-scherm.", "price": "639,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10442692, "category": "Hogedrukreiniger", "name": "K 7 Full Control Plus", "description": "De K 7 Full Control Plus hogedrukreiniger van K\u00e4rcher inclusief hogedrukpistool met drukregeling en dosering van reinigingsmiddel met een druk op de knop, en een LCD-scherm waarop de druk wordt weergegeven.", "price": "579,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10462452, "category": "Hogedrukreiniger", "name": "K 5 Premium Full Control Plus Home", "description": "K 5 Premium Full Control Plus Home hogedrukreiniger met +/- knoppen voor drukregeling en LCD-scherm op het hogedrukpistool. Inclusief Home Kit, 3-in-1 Multi Jet spuitlans en slanghaspel.", "price": "499,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10442700, "category": "Hogedrukreiniger", "name": "K 5 Premium Full Control Plus", "description": "Voor regelmatig verwijderen van matige verontreiniging op auto's, stenen muren en fietsen. K 5 Premium Full Control Plus hogedrukreiniger inclusief hogedrukpistool met +/- knoppen voor drukregeling en LCD-scherm.", "price": "449,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10430946, "category": "Hogedrukreiniger", "name": "K 5 Full Control", "description": "Hogedrukreiniger met drukindicator op het hogedrukpistool - voor de juiste druk op elk oppervlak. Ideaal voor regelmatig gebruik op matige verontreiniging. Oppervlakteprestatie van 40 m\u00b2/u.", "price": "379,95", "timestamp": "18-08-2019 15:53:30"},
{"productid": 10441978, "category": "Hogedrukreiniger", "name": "K 4 Premium Full Control Home", "description": "Hogedrukreiniger met drukindicator op het hogedrukpistool \u2013 voor de juiste druk op elk oppervlak. Inclusief slanghaspel en Home Kit. Ideaal voor een gemiddelde vervuilingsgraad. Oppervlakteprestatie van 30 m\u00b2/u.", "price": "369,95", "timestamp": "18-08-2019 15:53:30"}
]
Results.json #2
[
{"productid": 10461927, "category": "hogedrukreinigers", "name": "K 7 Premium Full Control Plus Home", "description": "Inclusief slanghaspel en Home Kit: de K 7 Premium Full Control Plus Home. U kunt de juiste druk instellen met de +/- knoppen en de LCD-scherm op het hogedrukpistool van de hogedrukreiniger.", "price": "699,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10453128, "category": "hogedrukreinigers", "name": "K 7 Premium Full Control Plus", "description": "Inclusief slanghaspel: de K 7 Premium Full Control Plus. U kunt de juiste druk instellen met de +/- knoppen en het LCD-scherm op het hogedrukpistool van de hogedrukreiniger.", "price": "639,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10461929, "category": "hogedrukreinigers", "name": "K 7 Full Control Plus Home", "description": "De ideale hogedrukreiniger voor regelmatig gebruik op hardnekkig vuil. K 7 Full Control Plus Home met Home Kit en hogedrukpistool inclusief +/- knoppen voor drukregeling en LCD-scherm.", "price": "639,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10442692, "category": "hogedrukreinigers", "name": "K 7 Full Control Plus", "description": "De K 7 Full Control Plus hogedrukreiniger van K\u00e4rcher inclusief hogedrukpistool met drukregeling en dosering van reinigingsmiddel met een druk op de knop, en een LCD-scherm waarop de druk wordt weergegeven.", "price": "579,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10462452, "category": "hogedrukreinigers", "name": "K 5 Premium Full Control Plus Home", "description": "K 5 Premium Full Control Plus Home hogedrukreiniger met +/- knoppen voor drukregeling en LCD-scherm op het hogedrukpistool. Inclusief Home Kit, 3-in-1 Multi Jet spuitlans en slanghaspel.", "price": "499,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10442700, "category": "hogedrukreinigers", "name": "K 5 Premium Full Control Plus", "description": "Voor regelmatig verwijderen van matige verontreiniging op auto's, stenen muren en fietsen. K 5 Premium Full Control Plus hogedrukreiniger inclusief hogedrukpistool met +/- knoppen voor drukregeling en LCD-scherm.", "price": "449,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10430946, "category": "hogedrukreinigers", "name": "K 5 Full Control", "description": "Hogedrukreiniger met drukindicator op het hogedrukpistool - voor de juiste druk op elk oppervlak. Ideaal voor regelmatig gebruik op matige verontreiniging. Oppervlakteprestatie van 40 m\u00b2/u.", "price": "379,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10441978, "category": "hogedrukreinigers", "name": "K 4 Premium Full Control Home", "description": "Hogedrukreiniger met drukindicator op het hogedrukpistool \u2013 voor de juiste druk op elk oppervlak. Inclusief slanghaspel en Home Kit. Ideaal voor een gemiddelde vervuilingsgraad. Oppervlakteprestatie van 30 m\u00b2/u.", "price": "369,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10491477, "category": "window vacs", "name": "WV 6 + KV 4(wit)", "description": "De vibrerende accu-wisser KV 4 inclusief elektrische bevochtiging, vibratie, tweede wisdoek en meer accessoires maakt het vuil los - en de Window Vac WV 6 zuigt het achterblijvende water af.", "price": "169,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10491478, "category": "window vacs", "name": "WV 6 + KV 4", "description": "Schone vensters in een handomdraai: met de vibrerende Window Vac KV 4 inclusief elektrische watervoorziening en vibratie maakt u het vuil eerst los en daarna zuigt u met de Window Vac WV 6 het vuile water af.", "price": "159,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10491479, "category": "window vacs", "name": "WV 6 Plus (wit)", "description": "In een set met 2 wisdoeken voor binnen en buiten, sproeiflacon, reinigingsmiddel en vuilkrabber: de Window Vac WV 6 Premium met innovatieve zuigstrip is nog flexibeler in gebruik.", "price": "109,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10491480, "category": "window vacs", "name": "WV 6 Plus", "description": "Met innovatieve striptechnologie en nog flexibeler in gebruik: de Window Vac WV 6 Plus voor streepvrij schone vensters in een mum van tijd.", "price": "99,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10491481, "category": "window vacs", "name": "WV 2 + KV4 (wit)", "description": "Sterk duo voor streepvrij schone vensters: de vibrerende accu-wisser KV 4 inclusief elektrische bevochtiging, vibratie, tweede wisdoek en meer extra's, en de Window Vac WV 2.", "price": "139,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10491482, "category": "window vacs", "name": "WV 2 + KV 4", "description": "Voor moeiteloos ramen lappen: de vibrerende accu-wisser KV 4 inclusief elektrische watervoorziening en trilfunctie maakt het vuil los - en de Window Vac WV 2 zuigt het vuile water af.", "price": "129,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10475755, "category": "window vacs", "name": "KV 4 Premium", "description": "Inclusief tweede wisdoek: de Window Vac KV 4 met elektrische watervoorziening en ondersteunende trilfunctie maakt het vuil moeiteloos los van alle gladde oppervlakken.", "price": "89,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10475756, "category": "window vacs", "name": "KV 4", "description": "De vibrerende accu-wisser KV 4 maakt vuil moeiteloos los van gladde oppervlakken. Door het elektrisch aangebrachte water en de trillingen wordt handmatig schrobben overbodig.", "price": "79,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10430942, "category": "hogedrukreinigers", "name": "K 4 Premium Full Control", "description": "Hogedrukreiniger met drukindicator op het hogedrukpistool - voor de juiste druk op elk oppervlak. Inclusief slanghaspel. Ideaal voor matige verontreiniging. Oppervlakteprestatie van 30 m\u00b2/u.", "price": "319,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10441943, "category": "hogedrukreinigers", "name": "K 4 Full Control Home", "description": "Hogedrukreiniger met drukindicator op het hogedrukpistool \u2013 voor de juiste druk op elk oppervlak. Ideaal voor de incidentele reiniging van een gemiddelde vervuiling. Inclusief Home Kit. Oppervlakteprestatie van 30 m\u00b2/u.", "price": "339,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10430938, "category": "hogedrukreinigers", "name": "K 4 Full Control", "description": "Hogedrukreiniger met drukindicator op het hogedrukpistool \u2013 voor de juiste druk op elk oppervlak. Ideaal voor de incidentele reiniging van een gemiddelde vervuiling. Oppervlakteprestatie van 30 m\u00b2/u.", "price": "289,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10501457, "category": "hogedrukreinigers", "name": "K 3 Full Control Home T150", "description": "Perfect schoon rondom huis dankzij de Home Kit inclusief oppervlaktereiniger en reinigingsmiddelen. Het pistool van de K 3 Full Control Home hogedrukreiniger geeft het drukniveau aan.", "price": "209,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10501459, "category": "hogedrukreinigers", "name": "K 3 Full Control", "description": "Ideale hogedrukreiniger voor incidenteel gebruik bij lichte vervuiling. De K 3 Full Control geeft de druk aan op het pistool. Zo kunt u voor elk oppervlak de juiste druk instellen.", "price": "179,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10406424, "category": "hogedrukreinigers", "name": "K 3 Home", "description": "De K 3 Home hogedrukreiniger met Home Kit is ideaal voor incidenteel gebruik en voor de verwijdering van lichte vervuiling op bijvoorbeeld fietsen, tuinhekken en motorfietsen.", "price": "219,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10461899, "category": "hogedrukreinigers", "name": "K 2 Premium Full Control Home", "description": "De K 2 Premium Full Control Home hogedrukreiniger van K\u00e4rcher inclusief Home Kit en met gerichte drukregeling. Ideaal voor oppervlakken rondom het huis en op lichtere vervuiling.", "price": "179,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10464555, "category": "hogedrukreinigers", "name": "K 2 HOME T150", "description": "De K 2 Home op wieltjes is speciaal ontworpen voor incidenteel gebruik en lichte vervuiling. Dankzij de Home Kit houdt u met de hogedrukreiniger ook grotere oppervlakken rondom het huis eenvoudig schoon.", "price": "129,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10479573, "category": "hogedrukreinigers", "name": "K 2 Basic", "description": "De 'K2 Basic' hogedrukreiniger is ideaal voor incidenteel gebruik en verwijdering van normale vervuiling rondom de woning (bijv. fietsen, tuingereedschap, tuinmeubilair).", "price": "79,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10497774, "category": "hogedrukreinigers", "name": "K 7 Compact Home", "description": "Compact en handzaam: de hogedrukreiniger K 7 Compact met watergekoelde motor. Voor frequent gebruik en sterke vervuiling, bijvoorbeeld op straten, in zwembaden, op fietsen of grote auto's.", "price": "589,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10497770, "category": "hogedrukreinigers", "name": "K 5 Compact Home", "description": "De K5 Compact Home met watergekoelde motor neemt weinig ruimte in en kan comfortabel worden vervoerd. Hogedrukreiniger inclusief Home Kit met oppervlaktereiniger T 350 en steen- en gevelreiniger.", "price": "379,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10497773, "category": "hogedrukreinigers", "name": "K 5 Compact", "description": "Inclusief innovatieve slangopberging: de eenvoudig te vervoeren en op te bergen hogedrukreiniger K 5 Compact voor regelmatig gebruik bij middelzware vervuiling. Oppervlakteprestatie 40 m\u00b2/u.", "price": "329,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10497765, "category": "hogedrukreinigers", "name": "K 4 Compact Home", "description": "Eenvoudig te vervoeren en snel op te bergen: de K 4 Compact voor incidenteel gebruik bij middelzware vervuiling. Inclusief telescoopgreep en watergekoelde motor. Oppervlakteprestatie 30 m\u00b2/u.", "price": "289,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10497768, "category": "hogedrukreinigers", "name": "K 4 Compact", "description": "Eenvoudig te vervoeren en snel op te bergen: de K 4 Compact voor incidenteel gebruik bij middelzware vervuiling. Inclusief telescoopgreep en watergekoelde motor. Oppervlakteprestatie 30 m\u00b2/u.", "price": "249,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10472949, "category": "hogedrukreinigers", "name": "K 2 Battery Set", "description": "Kan overal worden ingezet waar er geen stopcontact beschikbaar is: De K2 hogedrukreiniger met accuaandrijving, inclusief 36 V li-ionaccu en oplader. Ideaal voor uiteenlopende toepassingen.", "price": "399,95", "timestamp": "18-08-2019 16:43:57"},
{"productid": 10472950, "category": "hogedrukreinigers", "name": "K 2 Battery", "description": "De hogedrukreiniger met accuaandrijving voor flexibel schoonmaken zonder stopcontact. Ideaal voor uiteenlopende toepassingen rondom het huis. Accu en oplader worden niet meegeleverd.", "price": "199,95", "timestamp": "18-08-2019 16:43:58"}
]
You need to yield category from CSV file to the parse using request.meta:
def start_requests(self):
"""Read keywords from keywords file amd construct the search URL"""
with open(os.path.join(os.path.dirname(__file__), "../resources/keywords.csv")) as search_keywords:
for keyword in csv.DictReader(search_keywords):
search_text=keyword["keyword"]
category = keyword["keywordtype"]
url="https://www.kaercher.com/api/v1/products/search/shoppableproducts/partial/{0}?page=1&size=8&isocode=nl-NL".format(
search_text)
# The meta is used to send our search text into the parser as metadata
yield scrapy.Request(url, callback = self.parse, meta = {"search_text": search_text, "category": category})
def parse(self, response):
category = response.meta["category"]
...
UPDATE
If you want to have your category on next page you need to use .meta again:
#Checking whether "isTruncated" is true (boolean), if so, next page will be triggered
if data["isTruncated"]:
yield scrapy.Request(
url="https://www.kaercher.com/api/v1/products/search/shoppableproducts/partial/20035386?page={page}&size=8&isocode=nl-NL".format(page=next_page),
callback=self.parse,
meta={'page': next_page, "category": category},
)
Related
count, print out and delete rows that do not contain a digit
Please see the following minimal reproducible example. {'URL': {68020: 'URL', 68021: 'https://www.funda.nl/koop/verkocht/vlijmen/huis-42544400-oranjelaan-55/'}, 'OfferedSince': {68020: 'OfferedSince', 68021: '20 december 2021'}, 'DateOfSale': {68020: 'DateOfSale', 68021: '22 december 2021'}, 'AskingPrice': {68020: 'AsingPrice', 68021: '269000 '}, 'Description': {68020: 'Description', 68021: 'Interessante royale woning, uitgebouwd op de begane grond, deels verbouwd en gemoderniseerd. Voorzien van een riante woonkamer met airconditioning, moderne halfopen keuken met inbouwapparatuur. De woning heeft in 2021 een nieuw dak gekregen en is voorzien van een twaalftal zonnepanelen. Op een aantal punten dient de woning nog te worden aangepast/afgerond maar dat is grotendeels al gereed. Centrale ligging nabij alle benodigde faciliteiten zoals winkels, scholen, busverbinding en goede aansluiting met de A59 waardoor steden als ’s-Hertogenbosch, Waalwijk en Tilburg goed bereikbaar zijn. Tevens liggen de Loonse- en Drunense Duinen en vestingstad Heusden op een steenworp afstand. Indeling Begane grond Entree/Hal Entree aan de voorzijde van de woning. Je komt binnen in de hal welke is voorzien van de meterkast (groepenkast 2021, glasvezel, aansluiting voor inductie koken aanwezig), de omvormer van de 12 zonnepanelen, toegang naar de multifunctionele ruimte met bijkeuken en de trapopgang naar de eerste verdieping. Multifunctionele ruimte / bijkeuken. Van oorsprong is de woning van het type drive-in, dat wil zeggen dat er oorspronkelijk een garage op de begane grond is gelegen. In de loop van de jaren is er een pui geplaatst op de plek van de garagedeur waardoor er nu een multifunctionele ruimte is ontstaan. Ideaal voor kantoor aan huis. Er is op de begane grond een extra toilet geplaatst. In de multifunctionele ruimte is de van oorsprong gelegen smeerput nog gelegen, deze is momenteel dichtgezet. Aan de achterzijde is de opstelplaats van wasmachine en droger. De multifunctionele ruimte is niet volledig afgebouwd en behoeft nog de nodige werkzaamheden om het af te ronden. Separaat is de bijkeuken gelegen met een volledig keukenblok voorzien van wasbak en gaskookplaat. In de tussenruimte is een extra kast voorzien van koel-vriescombinatie. Op deze verdieping is tevens de CV ketel geplaatst (Intergas 2012). Dit betreft een CV ketel die geleased is inclusief onderhoudscontract. Vanuit de multifunctionele ruimte bereik je de achtertuin. Eerste verdieping Via de trap bereik je de eerste verdieping en kom je op de overloop waar zich het toilet en een extra kast bevinden. Hier is te trap naar de tweede verdieping en de toegang naar de woonkamer. Woonkamer en keuken Bij binnenkomst in de woonkamer valt meteen de hoeveelheid lichtinval op. Het is een ruime en erg lichte ruimte. Voorzien van een fraaie massief houtenvloer. Aan de achterzijde is de eetruimte welke aaneengesloten is aan de ruime keuken. Hier is de airconditioning geplaatst welke de volledige verdieping in warme dagen koel houdt. De keuken is voorzien van een combi-stoomoven, koel-vriescombinatie, een 4-pits gaskookplaat en RVS afzuigkap, vaatwasser en spoelbak. Tevens is er veel kast- en opbergruimte. Het bouwjaar van de keuken dateert van 2012. In de keuken is een tegelvloer gelegen. Tweede verdieping Via een vaste trap is de tweede verdieping bereikbaar. Hier bevinden zich 3 slaapkamers en de badkamer. De eerste slaapkamer is aan de voorzijde gelegen. Deze kamer is voorzien van een airconditioning en een fraaie laminaatvloer. Slaapkamer twee ligt aan de achterzijde en is nog af te ronden, de huidige eigenaren hebben deze kamer momenteel niet in gebruik. De derde slaapkamer is ook aan de achterzijde gelegen en is, net als de overloop en eerste slaapkamer, voorzien van een fraaie laminaatvloer. Op de overloop komt daglicht via de lichtkoepel. Het plafond dient nog afgerond te worden. Het plattedak van het hoofdgebouw dateert van 2021 evenals de 12 zonnepanelen. Badkamer De badkamer is modern en deels betegeld, deels gestuukt en voorzien van een inloopdouche met glazen wanden, een wandcloset en een wastafel. Exterieur Achtertuin Vanuit de multifunctionele ruimte is de achtertuin bereikbaar. De tuin is ruim van opzet en dient nog aangelegd te worden. Oprit Aan de voorzijde van de woning is een oprit waar 2 auto’s geparkeerd kunnen worden aanwezig. Bijzonderheden * Volledig nieuw dak op het hoofdhuis (2021) voorzien van 12 zonnepanelen (2021) * Mooie riante moderne woonkeuken (2012) * Ruime en lichte woonkamer * 3 slaapkamers en moderne badkamer * Oprit voor 2 auto’s * Multifunctionele ruimte op de begane grond * Mooie ligging tegenover een speelparkje * De woning dient op een aantal punten nog afgebouwd/afgerond te worden'}, 'Postcode': {68020: 'Postcode', 68021: '5251 JK'}, 'LivingArea': {68020: 'LivingArea', 68021: '158 '}, 'PlotArea': {68020: 'PlotArea', 68021: '196 '}, 'Rooms': {68020: 'Rooms', 68021: '6'}, 'Bedrooms': {68020: 'Bedrooms', 68021: '3'}, 'Bathrooms': {68020: 'Bathrooms', 68021: '1'}, 'EnergyLabel': {68020: 'EnergyLabel', 68021: 'A'}, 'BuildYear': {68020: 'BuildYear', 68021: '1969'}, 'TypeOfHouse': {68020: 'TypeOfHouse', 68021: 'Eengezinswoning, tussenwoning (drive-in woning)'}, 'Garden': {68020: 'Garden', 68021: 'Achtertuin en voortuin'}, 'Garden-yes-no': {68020: 'Garden-yes-no', 68021: 'Yes'}} I would like to print out all the rows that do not contain a digit in the 'AskingPrice' column. In the above reproducible example, this would be the row 68020. What is the most efficient way to select a row that does not contain a digit? Thanks in advance.
You could try this: import pandas as pd df = pd.pd.DataFrame(dict_you_provided) print(df[df["AskingPrice"].astype(str).str.contains(pat="[a-zA-Z]", regex=True)]) # Output URL OfferedSince DateOfSale AskingPrice ... BuildYear TypeOfHouse Garden Garden-yes-no 68020 URL OfferedSince DateOfSale AsingPrice ... BuildYear TypeOfHouse Garden Garden-yes-no
Flatening a JSONB column into a string in PostgreSQL
I am dealing with JSONB columns and its quite new to me. Below is the sample data set UUID Survey_id Employee_id Employee_Response Status f212 2 17 [{"q_id": "5", "answer": {"value": "Agree"}, "q_type": "radio-buttons"}, {"q_id": "6", "answer": {"value": "4"}, "q_type": "star-ratings"}, {"q_id": "7", "answer": {"value": "9"}, "q_type": "slider-type"}] active a3f5 2 46 [{"q_id": "5", "answer": {"value": "Agree"}, "q_type": "radio-buttons"}, {"q_id": "6", "answer": {"value": "4"}, "q_type": "star-ratings"}, {"q_id": "7", "answer": {"value": "8"}, "q_type": "slider-type"}] active 2db8 2 32 [{"q_id": "5", "answer": {"value": "Agree"}, "q_type": "radio-buttons"}, {"q_id": "6", "answer": {"value": "3"}, "q_type": "star-ratings"}, {"q_id": "7", "answer": {"value": "9"}, "q_type": "slider-type"}] active d2bd 2 40 [{"q_id": "5", "answer": {"value": "Disagree"}, "q_type": "radio-buttons"}, {"q_id": "6", "answer": {"value": "2"}, "q_type": "star-ratings"}, {"q_id": "7", "answer": {"value": "3"}, "q_type": "slider-type"}] active g632 2 31 [{"q_id": "5", "answer": {"value": "Strongly Agree"}, "q_type": "radio-buttons"}, {"q_id": "6", "answer": {"value": "3"}, "q_type": "star-ratings"}, {"q_id": "7", "answer": {"value": "6"}, "q_type": "slider-type"}] active Expected output UUID Survey_id Employee_id Q_5 Q_6 q_7 f212 2 17 Agree 4 9 a3f5 2 46 Agree 4 8 2db8 2 32 Agree 3 9 d2bd 2 40 Disagree 2 3 g632 2 31 Strongly Agree 3 6 Can you please suggest or help to achieve the same, I have tried below and other various methods but still not luck in achieving it in SQL SELECT survey_id, response::jsonb->'answer'->>'value' as name FROM survey_resposnes select survey_id,user_id, response-> 'q_id' #> '[5]' as q0--, from survey_resposnes
You can use jsonb_path_query_first() for this: select r."uuid", r.survey_id, r.employee_id, jsonb_path_query_first(r.employee_response, '$[*] ? (#.q_id == "5").answer.value') #>> '{}' as q_5, jsonb_path_query_first(r.employee_response, '$[*] ? (#.q_id == "6").answer.value') #>> '{}' as q_6, jsonb_path_query_first(r.employee_response, '$[*] ? (#.q_id == "7").answer.value') #>> '{}' as q_7 from survey_responses r jsonb_path_query_first() returns a jsonb value. To convert that into a proper text value, the #>> '{}' is used. If you are fine with a jsonb value as the result you can remove that expression Online example
is there's function to extract value from dictionary in list?
kindly need to extract name value, even it's Action or adventure from this column in new column in pandas '[{"id": 28, "name": "Action"}, {"id": 12, "name": "Adventure"}, {"id": 14, "name": "Fantasy"}, {"id": 878, "name": "Science Fiction"}]'
You want from_records: import pandas as pd data = [{"id": 28, "name": "Action"}, {"id": 12, "name": "Adventure"}, {"id": 14, "name": "Fantasy"}, {"id": 878, "name": "Science Fiction"}] df = pd.DataFrame.from_records(data) df you get id name 0 28 Action 1 12 Adventure 2 14 Fantasy 3 878 Science Fiction
amcharts v3 add legend to radar chart
I like to add a legend to my radar chard but i can not seem to connect the legend data to the dataprovider data Here is my javascript code: AmCharts.makeChart("360_radar_chartdiv", {"type": "radar", "dataProvider": [ {"competence": "test Ronald","user_15": 7.5,"user_16": 7.5,"user_18": 1,"user_23": 5}, {"competence": "Aansturen","user_15": 5,"user_16": 7,"user_18": 8,"user_23": 3}], "valueAxes": [ {"axisTitleOffset": 20, "minimum": 0,"maximum": 10, "axisAlpha": 0.15}], "startDuration": 0 , "graphs": [ {"balloonText": "[[value]]", "bullet": "round","valueField": "user_15"}, {"balloonText": "[[value]]", "bullet": "round","valueField": "user_16"}, {"balloonText": "[[value]]", "bullet": "round","valueField": "user_18"}, {"balloonText": "[[value]]", "bullet": "round","valueField": "user_23"} ], "categoryField": "competence", "legend": {"align": "center", "markerType": "circle", "position": "right","marginright": 80, "automargin": false, "combineLegend": true, "data": [ {"title": "Beheer B van (Proeftuin)"}, {"title": "Acda W. (Willem)"}, {"title": "Baard B. (Bas)"}, {"title": "Bedrijf 1 - Jan Stucadoor"}]} });
I have resolved this by putting the legend text in the graphs data: "graphs": [ {"balloonText": "[[value]] - van Beheer B van (Proeftuin)", "bullet": "round","valueField": "user_25"}, {"balloonText": "[[value]] - van Acda W. (Willem)", "bullet": "round","valueField": "user_26"}, {"balloonText": "[[value]] - van Rutte M.E. (Mark)", "bullet": "round","valueField": "user_27"}, {"balloonText": "[[value]] - van Bedrijf 1 - Persoon 1", "bullet": "round","valueField": "user_33"}]
REGEXP_SUBSTR Oracle | Extract a string between two delimiters
Im trying to extract a name from a column that return a big clob like this one: { "idStatus":6, "atrasoSLA":0.0, "atrasoSLAStr":"00:00", "baseReports":false, "idItemTrabalho":10019, "portfolio":"Segurança", "servicoRelacionado":"ATIVOS (SEGURANÇA)", "idStatusControleSla":8, "dataFinalUltimoControleSla":"Sep 3, 2018 11:55:12 AM", "grupoExecutor":"Segurança", "idGrupoExecutor":71, "contrato":"Central de Serviços - SEFAZ-MA", "dataHoraCaptura":"Sep 3, 2018 11:42:32 AM", "dataHoraFim":"Sep 3, 2018 11:55:12 AM", "dataHoraInicio":"Sep 3, 2018 11:42:19 AM", "dataHoraInicioSLA":"Sep 3, 2018 11:42:19 AM", "dataHoraInicioSLAStr":"09/03/2018 11:42 AM", "dataHoraLimite":"Sep 4, 2018 7:42:00 AM", "dataHoraLimiteStr":"09/04/2018 07:42 AM", "dataHoraSolicitacao":"Sep 3, 2018 11:42:19 AM", "dataHoraSolicitacaoStr":"09/03/2018 11:42 AM", "demanda":"Requisição", "descricao":"\u003cp\u003eRafael reportou que o CITSMART homologa\u0026ccedil;\u0026atilde;o\u0026nbsp;esta\u0026nbsp;offline.\u0026nbsp;\u003c/p\u003e\n", "descricaoSemFormatacao":"Rafael reportou que o CITSMART homologação esta offline. ", "descrSituacao":"citcorpore.comum.fechada", "detalhamentoCausa":"\u003cp\u003eO incidente foi causado devido o servidor de aplica\u0026ccedil;\u0026otilde;es do CITSMART estar em DHCP, com isso o IP 10.1.1.247 foi alterado para outro IP causando a falha na comunica\u0026ccedil;\u0026atilde;o com o APACHE.\u003c/p\u003e\n", "emailcontato":"rafael.feitosa#sefaz.ma.gov.br", "emailResponsavel":"nilson#sefaz.ma.gov.br", "enviaEmailAcoes":"S", "enviaEmailCriacao":"S", "enviaEmailFinalizacao":"S", "faseAtual":"Execução", "grupoNivel1":"SDNIVEL1", "idAcordoNivelServico":8, "idCalendario":2, "idContatoSolicitacaoServico":1844, "idContrato":2, "idFaseAtual":2, "idOrigem":1, "idPrioridade":5, "idServico":70, "idServicoContrato":61, "idSolicitacaoServico":1559, "idSolicitante":2220, "idTipoDemandaServico":1, "idUnidade":104, "idTarefaEncerramento":10019, "impacto":"B", "nomecontato":"Rafael Brito Feitosa", "nomeServico":"ATIVOS (SEGURANÇA) - Análise LOGs/Desempenho/Capacidade/Disponibilidade", "nomeTarefa":"Atender solicitacao", "nomeUnidadeResponsavel":"COTEC", "observacao":" ", "origem":"Central de Serviços", "prazoCapturaHH":0, "prazoCapturaMM":0, "prazoHH":8, "prazoMM":0, "prioridade":"5", "responsavel":"Nilson Roniery da Silva Vieira (COTEC)", "resposta":"\u003cp\u003ePara solucionar este foi inserido um IP fixo da DMZ EXTERNA e mais o seguintes passos:\u003c/p\u003e\n\n\u003col\u003e\n\t\u003cli\u003eAdicionado IP fixo na m\u0026aacute;quina, sendo ele: 172.20.1.55;\u003c/li\u003e\n\t\u003cli\u003eForam criadas regras no Firewall:\n\t\u003cul\u003e\n\t\t\u003cli\u003e172.20.1.55 --\u0026gt; 10.1.1.56 (BD) porta 1521\u003c/li\u003e\n\t\t\u003cli\u003e172.20.1.55 -\u0026gt;\u0026gt;\u0026nbsp; INTERNET portas 80 e 443\u003c/li\u003e\n\t\t\u003cli\u003eVPN CIT --\u0026gt;\u0026nbsp;172.20.1.55\u003c/li\u003e\n\t\u003c/ul\u003e\n\t\u003c/li\u003e\n\t\u003cli\u003eForam alterados os proxies no apache conforme imagem abaixo\u003cimg src\u003d\"/citsmart/galeriaImagens/1/2/439.png\" style\u003d\"height:105px; width:884px\" /\u003e\u003c/li\u003e\n\t\u003cli\u003eFoi restartado o servi\u0026ccedil;o do citsmart no AS.\u0026nbsp;\n\t\u003cul\u003e\n\t\t\u003cli\u003e\u003cem\u003e#\u0026nbsp;/etc/init.d/citsmart_itsm stop\u003c/em\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003cem\u003e# /etc/init.d/citsmart_itsm start\u003c/em\u003e\u003c/li\u003e\n\t\u003c/ul\u003e\n\t\u003c/li\u003e\n\u003c/ol\u003e\n", "seqReabertura":0, "servico":"ATIVOS (SEGURANÇA) - Análise LOGs/Desempenho/Capacidade/Disponibilidade", "situacaoSLA":"A", "slaACombinar":"N", "solicitante":"Rafael Brito Feitosa", "solicitanteUnidade":"Rafael Brito Feitosa", "solucaoTemporaria":"N", "telefonecontato":"Não disponível.", "tempoAtendimentoHH":0, "tempoAtendimentoMM":12, "tempoAtrasoHH":0, "tempoAtrasoMM":0, "tempoCapturaHH":0, "tempoCapturaMM":0, "tempoCapturaSS":13, "tempoDecorridoHH":0, "tempoDecorridoMM":0, "urgencia":"B", "ordernacao":0, "usuarioDto":{ "idUsuario":635, "idEmpregado":635, "idPerfilAcessoUsuario":6, "idEmpresa":1, "login":"sefaz.ma.gov.br\\034013", "nomeUsuario":"Nilson Roniery da Silva Vieira", "senha":"f04534e4998415904454ae1ceb2040fa05bf548e", "status":"A", "ldap":"S", "email":"nilson#sefaz.ma.gov.br", "ldapGroupId":1, "fromToken":false }, "idResponsavel":635, "idGrupoAtual":71, "idGrupoNivel1":2, "idTarefa":10019, "grupoAtual":"Segurança" } In this case the name i want is "Nilson Roniery da Silva" And the only thing i know is that the names always come after the "nomeUsuario":" and at the end have a " so, how can i make a select that only brings me the name between "nomeUsuario":" and "
You should be able to use json_value to parse this clob: SELECT JSON_VALUE(mycolumn, '$.usuarioDto.nomeUsuario') FROM mytable