Dutch Gas Priceses

I just tried you’re specific location with the select value as mentioned and it’s resulting in a value without any issues or errors. For the comparison, I’m running Homeassistant 73.1 with Docker.

Finally, it’s working.
Somehow I ended up with faulty quotes in my config…

  - platform: scrape
    resource: https://www.shellexpress.nl/nl_nl/station/se-nieuwerkerk-aan-den-ijssel
    name: Shell Express
    select: ".price-actual"
    value_template: '{{ value.split(" ")[0] }}'
    scan_interval: 3600

  - platform: scrape
    name: Tinq
    resource: "http://www.tinq.nl/tankstation?id=251"
    select: "#station-prijzen tr:nth-of-type(3) td:nth-of-type(2)"
    value_template: "{{ value.split('\xa0')[1].replace(' ','').replace(',', '.') | float }}"
    scan_interval: 3600 

  - platform: scrape
    resource: "http://lukoil.nl/go/lukoil_station.cfm?id=465"
    name: Lukoil
    select: "#tabbedInfoContent div:nth-of-type(14)"
    value_template: "{{ value.split('\x0D')[2].replace('EUR/L', '').replace(',', '.') | float }}"
    scan_interval: 3600 

  - platform: scrape
    resource: "https://www.tango.nl/stations/tango-nieuwerkerk-ad-ijssel"
    name: Tango
    select: “#euro95 .pump_price span.price” #<<<<<<<<<< FAULTY QUOTES
    scan_interval: 3600

If you look closely to the original example, that’s were they came from.

Using this for the last 3 months gave me some nice stats in Grafana, cleary showing how long they wait to drop the prices at Shell Express and how fast they raise the price. :money_mouth_face:

# Benzine Prijzen
  - platform: scrape
    name: Euro95
    resource: "https://www.unitedconsumers.com/brandstofprijzen"
    select: ".table div:nth-of-type(8)"
    value_template: "{{ value.split(' ')[1].replace(',', '.') | float }}"
    scan_interval: 3600 # be nice; once per hour only

  - platform: scrape
    resource: "https://shellexpress.nl/nl_nl/station/se-santpoort"
    name: Shell_Express_Santpoort
    select: ".price-actual"
    value_template: "{{ value.split(' ')[0].replace(',', '.') | float }}"
    scan_interval: 3600

But United Consumers seem to have done something in their website code resulting in a 0.0 price.
I have tried to make cheese how this scrape works with the inspect option from Google Chrome but no luck. :thinking:

Also Shell has changed the website for the individual tankstations. The url (“https://shellexpress.nl/nl_nl/station/se-pijnacker” in my case) now goes to a general page where you have to select a station. I haven’t found a fix for it yet sadly enough.

Not sure if its the website, I did read there was some fix in the scraper because of a bug the code for UnitedConsumer was working.

FYI i’m having the same issue resulting in a 0.0 price. Not sure how to fix as i have no experience with select part :frowning:

I still hope someone can make it work from the Directlease website?
Or other also good.
Looking for Esso Express and Texaco.
Tinq already work now

They changed a few things so I’ve updated your config and expanded it a little bit. I’m by no means a pro, just a noob trying stuff by trail and error.

You’ll need this, to make this work: https://github.com/kalkih/mini-graph-card

image

configuration 26/02/2019

customize.yaml

sensor.diesel_value:
  friendly_name: "Diesel"
  icon: mdi:gas-station
sensor.euro95_value:
  friendly_name: "Euro 95"
  icon: mdi:gas-station
sensor.lpg_value:
  friendly_name: "LPG"
  icon: mdi:gas-station

configuration.yaml

sensor:
# SCRAPING GAS PRICES
  - platform: scrape
    name: Euro95
    resource: "https://www.unitedconsumers.com/brandstofprijzen"
    select: "div.row:nth-of-type(2) div.col-xs-4:nth-of-type(3)"
    scan_interval: 3600
  - platform: scrape
    name: Diesel
    resource: "https://www.unitedconsumers.com/brandstofprijzen"
    select: "div.row:nth-of-type(3) div.col-xs-4:nth-of-type(3)"
    scan_interval: 3600
  - platform: scrape
    name: LPG
    resource: "https://www.unitedconsumers.com/brandstofprijzen"
    select: "div.row:nth-of-type(4) div.col-xs-4:nth-of-type(3)"
    scan_interval: 3600
# TEMPLATING GAS PRICES
  - platform: template
    sensors:
      euro95_value:
        friendly_name: "Euro 95"
        unit_of_measurement: "€/l"
        value_template: "{{ states('sensor.euro95') |replace('€', '') |replace(',', '.') |round(3) }}"
      diesel_value:
        friendly_name: "Diesel"
        unit_of_measurement: "€/l"
        value_template: "{{ states('sensor.diesel') |replace('€', '') |replace(',', '.') |round(3) }}"
      lpg_value:
        friendly_name: "LPG"
        unit_of_measurement: "€/l"
        value_template: "{{ states('sensor.lpg') |replace('€', '') |replace(',', '.') |round(3) }}"

ui-lovelace.yaml

      - type: vertical-stack
        cards:
          - type: markdown
            content: >
              ## <center>BRANDSTOF PRIJZEN</center>
          - type: entities
            entities:
              - sensor.euro95_value
              - sensor.diesel_value
              - sensor.lpg_value
          - type: horizontal-stack
            cards:
              - type: custom:mini-graph-card
                entities:
                  - entity: sensor.euro95_value
                name: Euro 95
                hour24: true
                font_size: 75
                decimals: 3
                show:
                  graph: bar
                points_per_hour: 0.25
                hours_to_show: 168
                line_color: '#7FFF00'
              - type: custom:mini-graph-card
                entities:
                  - entity: sensor.diesel_value
                name: Diesel
                hour24: true
                font_size: 75
                decimals: 3
                show:
                  graph: bar
                points_per_hour: 0.25
                hours_to_show: 168
                line_color: '#FF0000'
              - type: custom:mini-graph-card
                entities:
                  - entity: sensor.lpg_value
                name: LPG
                hour24: true
                font_size: 75
                decimals: 3
                show:
                  graph: bar
                points_per_hour: 0.25
                hours_to_show: 168
                line_color: '#FFF68F'

1 Like

I just dropped into this thread and made some adjustments.

Check my post.

YES!!! Got the “adviesprijs” back. Thank you so much!

Probably a change in the scraper. The 8th div was literal earlier, but now it is in the hierarchy. This is my adjusted config

sensor:
  - platform: scrape
    name: Euro95 Advies
    resource: "https://www.unitedconsumers.com/brandstofprijzen"
    select: ".table div:nth-of-type(2) div:nth-of-type(3)"
    value_template: "{{ value |replace('€', '') |replace(',', '.') |round(3) }}"
    scan_interval: 3600 # be nice; once per hour only

  - platform: scrape
    name: Diesel Advies
    resource: "https://www.unitedconsumers.com/brandstofprijzen"
    select: ".table div:nth-of-type(3) div:nth-of-type(3)"
    value_template: "{{ value |replace('€', '') |replace(',', '.') |round(3) }}"
    scan_interval: 3600 # be nice; once per hour only

  - platform: scrape
    name: LPG Advies
    resource: "https://www.unitedconsumers.com/brandstofprijzen"
    select: ".table div:nth-of-type(4) div:nth-of-type(3)"
    value_template: "{{ value |replace('€', '') |replace(',', '.') |round(3) }}"
    scan_interval: 3600 # be nice; once per hour only
2 Likes

Thanks that did the trick :slight_smile:

My solution to the prices was a python3 script:

from bs4 import BeautifulSoup
import requests
import json


###Take the url name from "https://www.brandstof-zoeker.nl/"
###Example: "https://www.brandstof-zoeker.nl/station/avia-h-i-ambacht-hendrik-ido-ambacht-771/"
###Mutiple stations supported (comma seprated)
stationList = ['avia-h-i-ambacht-hendrik-ido-ambacht-771']

list = {}

for station in stationList:
    stationName = station.split('-',1)[0]

    ###load website with request
    result = requests.get("https://www.brandstof-zoeker.nl/station/{0}/".format(station))
    ###Get content from request website
    content = result.content

    ###Load content in bs4
    soup = BeautifulSoup(content, "html.parser")

    ###Put body in variable
    soupBody = soup.body

    ###try if available, catches errors
    try:
        diesel = soupBody.find_all('dd')[0]
    except IndexError:
        diesel = 'null'
    
    ###try if available, catches errors
    try:
        euro95 = soupBody.find_all('dd')[1]
    except IndexError:
        euro95 = 'null'


    ###If error change both values to not available, prevents euro95 and diesel pricing mixup
    if euro95 == 'null' or diesel == 'null':
        dieselClean = "Not available"
        euro95Clean = "Not available"
    else:
        ###Gets pricing line from beautifull soup input
        diesel = soupBody.find_all('dd')[0]
        euro95 = soupBody.find_all('dd')[1]
        ###Strips everything except price
        euro95Clean = str(euro95).split('\n',1)[-1].split('\n', 1)[0].split(' ', 1)[-1].split(' ', 1)[0]
        dieselClean = str(diesel).split('\n',1)[-1].split('\n', 1)[0].split(' ', 1)[-1].split(' ', 1)[0]

    ###creates a list in json format so homeassistant templates can be used.
    list["{0}".format(stationName)] = {"euro95": "{0}".format(euro95Clean),"diesel": "{0}".format(dieselClean)}

encapsulatedList = {"list": list}

json = json.dumps(encapsulatedList)

print(json)

This script outputs a JSON array with the prices. Next I added a sensor in hass to get the output as a sensor.

- platform: command_line
  name: 'gasPrice'
  command: "python /config/scripts/gasprice/gasPrices.py"
  scan_interval: 60
  json_attributes: ['list']

To avoid multiple request to the site for every gasstation I created a template to extract the data from the commandline sensor to sepperate entities. This I did with the following sensors:

- platform: template
  sensors:
    shell_euro95:
      unit_of_measurement: '€'
      value_template: >-
        {{- state_attr('sensor.gasPrice', 'list').shell.euro95 -}}
    berkman_euro95:
      unit_of_measurement: '€'
      value_template: >-
        {{- state_attr('sensor.gasPrice', 'list').berkman.euro95 -}}
2 Likes

Works perfect! Too bad the Tamoil close by doesn’t give any information via www.brandstof-zoeker.nl.
But even for a n00b like me, I got it working. Thanks!

Tinq has recenlty done an update on their site, so the example in this topic doesn’t work anymore.

I am now playing with BeautifulSoup to get the diesel price from my local fueling station, but I have too little experience to get there. Is there anyone able to help?

What I have so far is:

import requests
from bs4 import BeautifulSoup

page = requests.get("https://www.tinq.nl/tankstations/nootdorp-kerkweg")
soup = BeautifulSoup(page.content, 'html.parser')
soupBody = soup.body

diesel = soupBody.select("div.field.field--name-field-station-prices.field--type-entity-reference.field--label-above > div.field__items > div:nth-child(1) > div > div.field.field--name-field-prices-price-pump.field--type-float.field--label-hidden.field__item")

print(diesel)

this is the output:

[<div class="field field--name-field-prices-price-pump field--type-float field--label-hidden field__item" content="1.349">€ 1.34<sup>9</sup><span>EUR/L</span></div>]

And that’s where I’m stuck at the moment. I see the correct price in the content tag, so that would be the easiest place in my opinion to get the price from, but how do I get it from there?

edit: sometimes it helps to ask for help to get to the sollution yourself :slight_smile:

looking at the example from @legoracers I found the following sollution:

dieselstripped = str(diesel).split('=',2)[-1].split('>',1)[0].split('"')[1]
print(dieselstripped)

or (even shorter)

dieselstripped = str(diesel).split('"')[3]

Maybe not the best sollution, but it works for now!

You can have a look at the fuel package in my configuration repo for Tinq using the scrape sensor.

BTW, Lukoil also changed their website recently. I fixed that as well.

Hero! I just noticed my Tinq sensors were broken for a long time and finally decided to check their website. That has changed quite a bit :slight_smile:

Your code works excellent. Direct link for others (as it includes more brands): https://github.com/metbril/home-assistant-config/blob/00d68bae7c6ec525ea28c712773645acd42b9a7d/packages/fuel.yaml

As i needed quite a few vendors I decided to go another way and build an OCR api on top of directlease.nl. You can try it here:
https://brandstof-api.sanwil.net/docs#/default/api_brandstof_prijs_api_v1_brandstof_prijzen__png__get
Just paste in a png filename such as “7025.png” (i didn’t see the numbers switching over time).

Direct endpoint would be “https://brandstof-api.sanwil.net/api/v1/brandstof_prijzen/7025.png” for example.

Let me know what you think. Later on i can make it run faster (it’s on a slow server now). For now it supplies the gasoline and diesel prices. ocr_station is just an indication of the first OCR line in the image, so don’t use it.

2 Likes

Whoa, you’re taking this to a whole different level this way!

I just need the diesel and benzine prices of 2 different TinQ stations, so the scrape is fine for me now.

I was just playing with the scrape function but I was not able to get the data from the esso and shell sites so I will look to your solution. I’ll tried a few and it seems to work fine, not slow at all. As a copy-paste programmer I have to look how to get the data into HA.