From 9c41f1173ad0962e5ecc529abd1107017d3aa26e Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sat, 12 Jan 2013 12:35:26 +0100 Subject: [PATCH 1/3] Fix amazon stores to account for website change. --- .../gui2/store/stores/amazon_plugin.py | 28 +++++++------------ .../gui2/store/stores/amazon_uk_plugin.py | 16 +++-------- 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/calibre/gui2/store/stores/amazon_plugin.py b/src/calibre/gui2/store/stores/amazon_plugin.py index 4bd1a42c9d..e26aa2a133 100644 --- a/src/calibre/gui2/store/stores/amazon_plugin.py +++ b/src/calibre/gui2/store/stores/amazon_plugin.py @@ -6,8 +6,6 @@ __license__ = 'GPL 3' __copyright__ = '2011, John Schember ' __docformat__ = 'restructuredtext en' -import random -import re from contextlib import closing from lxml import html @@ -130,16 +128,16 @@ class AmazonKindleStore(StorePlugin): data_xpath = '//div[contains(@class, "prod")]' format_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and not(contains(@class, "bld"))]/text()' - asin_xpath = './/div[@class="image"]/a[1]' + asin_xpath = '@name' cover_xpath = './/img[@class="productImage"]/@src' title_xpath = './/h3[@class="newaps"]/a//text()' author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()' price_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and contains(@class, "bld")]/text()' - + for data in doc.xpath(data_xpath): if counter <= 0: break - + # Even though we are searching digital-text only Amazon will still # put in results for non Kindle books (author pages). Se we need # to explicitly check if the item is a Kindle book and ignore it @@ -147,21 +145,15 @@ class AmazonKindleStore(StorePlugin): format = ''.join(data.xpath(format_xpath)) if 'kindle' not in format.lower(): continue - + # We must have an asin otherwise we can't easily reference the # book later. - asin_href = None - asin_a = data.xpath(asin_xpath) - if asin_a: - asin_href = asin_a[0].get('href', '') - m = re.search(r'/dp/(?P.+?)(/|$)', asin_href) - if m: - asin = m.group('asin') - else: - continue + asin = data.xpath(asin_xpath) + if asin: + asin = asin[0] else: continue - + cover_url = ''.join(data.xpath(cover_xpath)) title = ''.join(data.xpath(title_xpath)) @@ -172,9 +164,9 @@ class AmazonKindleStore(StorePlugin): pass price = ''.join(data.xpath(price_xpath)) - + counter -= 1 - + s = SearchResult() s.cover_url = cover_url.strip() s.title = title.strip() diff --git a/src/calibre/gui2/store/stores/amazon_uk_plugin.py b/src/calibre/gui2/store/stores/amazon_uk_plugin.py index 0f9caf8f3e..486671c729 100644 --- a/src/calibre/gui2/store/stores/amazon_uk_plugin.py +++ b/src/calibre/gui2/store/stores/amazon_uk_plugin.py @@ -6,8 +6,6 @@ __license__ = 'GPL 3' __copyright__ = '2011, John Schember ' __docformat__ = 'restructuredtext en' -import re - from contextlib import closing from lxml import html @@ -53,7 +51,7 @@ class AmazonUKKindleStore(StorePlugin): data_xpath = '//div[contains(@class, "prod")]' format_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and not(contains(@class, "bld"))]/text()' - asin_xpath = './/div[@class="image"]/a[1]' + asin_xpath = '@name' cover_xpath = './/img[@class="productImage"]/@src' title_xpath = './/h3[@class="newaps"]/a//text()' author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()' @@ -73,15 +71,9 @@ class AmazonUKKindleStore(StorePlugin): # We must have an asin otherwise we can't easily reference the # book later. - asin_href = None - asin_a = data.xpath(asin_xpath) - if asin_a: - asin_href = asin_a[0].get('href', '') - m = re.search(r'/dp/(?P.+?)(/|$)', asin_href) - if m: - asin = m.group('asin') - else: - continue + asin = data.xpath(asin_xpath) + if asin: + asin = asin[0] else: continue From a84feb91b77f1252f78cfe5fe39bbfc60aca9111 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 13 Jan 2013 11:23:43 +0100 Subject: [PATCH 2/3] Libre.de changed its name to ebook.de. --- src/calibre/customize/builtins.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index a6dde30a94..20552d5d9c 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -1471,9 +1471,9 @@ class StoreLegimiStore(StoreBase): affiliate = True class StoreLibreDEStore(StoreBase): - name = 'Libri DE' + name = 'ebook.de' author = 'Charles Haley' - description = u'Sicher Bücher, Hörbücher und Downloads online bestellen.' + description = u'All Ihre Bücher immer dabei. Suchen, finden, kaufen: so einfach wie nie. ebook.de war libre.de' actual_plugin = 'calibre.gui2.store.stores.libri_de_plugin:LibreDEStore' headquarters = 'DE' From 41224d8ba0cd662c6d109deb22a7764cefd230e1 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 15 Jan 2013 10:58:07 +0100 Subject: [PATCH 3/3] 1) Make amazon EU plugins self sufficient 2) Fix broken waterstores UK store. --- .../gui2/store/stores/amazon_de_plugin.py | 95 ++++++++++++++++++- .../gui2/store/stores/amazon_es_plugin.py | 94 +++++++++++++++++- .../gui2/store/stores/amazon_fr_plugin.py | 95 ++++++++++++++++++- .../gui2/store/stores/amazon_it_plugin.py | 95 ++++++++++++++++++- .../gui2/store/stores/amazon_uk_plugin.py | 29 +++--- .../store/stores/waterstones_uk_plugin.py | 4 +- 6 files changed, 392 insertions(+), 20 deletions(-) diff --git a/src/calibre/gui2/store/stores/amazon_de_plugin.py b/src/calibre/gui2/store/stores/amazon_de_plugin.py index 58c67122e1..71ed8b0491 100644 --- a/src/calibre/gui2/store/stores/amazon_de_plugin.py +++ b/src/calibre/gui2/store/stores/amazon_de_plugin.py @@ -7,9 +7,100 @@ __license__ = 'GPL 3' __copyright__ = '2011, John Schember ' __docformat__ = 'restructuredtext en' -from calibre.gui2.store.stores.amazon_uk_plugin import AmazonUKKindleStore +from contextlib import closing +from lxml import html -class AmazonDEKindleStore(AmazonUKKindleStore): +from PyQt4.Qt import QUrl + +from calibre.gui2.store import StorePlugin +from calibre import browser +from calibre.gui2 import open_url +from calibre.gui2.store.search_result import SearchResult + + + +# This class is copy/pasted from amason_uk_plugin. Do not modify it in any +# other amazon EU plugin. Be sure to paste it into all other amazon EU plugins +# when modified. + +class AmazonEUBase(StorePlugin): + ''' + For comments on the implementation, please see amazon_plugin.py + ''' + + def open(self, parent=None, detail_item=None, external=False): + + store_link = self.store_link % self.aff_id + if detail_item: + self.aff_id['asin'] = detail_item + store_link = self.store_link_details % self.aff_id + open_url(QUrl(store_link)) + + def search(self, query, max_results=10, timeout=60): + url = self.search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+') + br = browser() + + counter = max_results + with closing(br.open(url, timeout=timeout)) as f: + doc = html.fromstring(f.read())#.decode('latin-1', 'replace')) + + data_xpath = '//div[contains(@class, "prod")]' + format_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and not(contains(@class, "bld"))]/text()' + asin_xpath = '@name' + cover_xpath = './/img[@class="productImage"]/@src' + title_xpath = './/h3[@class="newaps"]/a//text()' + author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()' + price_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and contains(@class, "bld")]/text()' + + for data in doc.xpath(data_xpath): + if counter <= 0: + break + + # Even though we are searching digital-text only Amazon will still + # put in results for non Kindle books (author pages). Se we need + # to explicitly check if the item is a Kindle book and ignore it + # if it isn't. + format_ = ''.join(data.xpath(format_xpath)) + if 'kindle' not in format_.lower(): + continue + + # We must have an asin otherwise we can't easily reference the + # book later. + asin = data.xpath(asin_xpath) + if asin: + asin = asin[0] + else: + continue + + cover_url = ''.join(data.xpath(cover_xpath)) + + title = ''.join(data.xpath(title_xpath)) + author = ''.join(data.xpath(author_xpath)) + try: + if self.author_article: + author = author.split(self.author_article, 1)[1].split(" (")[0] + except: + pass + + price = ''.join(data.xpath(price_xpath)) + + counter -= 1 + + s = SearchResult() + s.cover_url = cover_url.strip() + s.title = title.strip() + s.author = author.strip() + s.price = price.strip() + s.detail_item = asin.strip() + s.drm = SearchResult.DRM_UNKNOWN + s.formats = 'Kindle' + + yield s + + def get_details(self, search_result, timeout): + pass + +class AmazonDEKindleStore(AmazonEUBase): ''' For comments on the implementation, please see amazon_plugin.py ''' diff --git a/src/calibre/gui2/store/stores/amazon_es_plugin.py b/src/calibre/gui2/store/stores/amazon_es_plugin.py index 427927a5a6..d613ced2a5 100644 --- a/src/calibre/gui2/store/stores/amazon_es_plugin.py +++ b/src/calibre/gui2/store/stores/amazon_es_plugin.py @@ -7,9 +7,99 @@ __license__ = 'GPL 3' __copyright__ = '2011, John Schember ' __docformat__ = 'restructuredtext en' -from calibre.gui2.store.stores.amazon_uk_plugin import AmazonUKKindleStore +from contextlib import closing +from lxml import html -class AmazonESKindleStore(AmazonUKKindleStore): +from PyQt4.Qt import QUrl + +from calibre.gui2.store import StorePlugin +from calibre import browser +from calibre.gui2 import open_url +from calibre.gui2.store.search_result import SearchResult + + +# This class is copy/pasted from amason_uk_plugin. Do not modify it in any +# other amazon EU plugin. Be sure to paste it into all other amazon EU plugins +# when modified. + +class AmazonEUBase(StorePlugin): + ''' + For comments on the implementation, please see amazon_plugin.py + ''' + + def open(self, parent=None, detail_item=None, external=False): + + store_link = self.store_link % self.aff_id + if detail_item: + self.aff_id['asin'] = detail_item + store_link = self.store_link_details % self.aff_id + open_url(QUrl(store_link)) + + def search(self, query, max_results=10, timeout=60): + url = self.search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+') + br = browser() + + counter = max_results + with closing(br.open(url, timeout=timeout)) as f: + doc = html.fromstring(f.read())#.decode('latin-1', 'replace')) + + data_xpath = '//div[contains(@class, "prod")]' + format_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and not(contains(@class, "bld"))]/text()' + asin_xpath = '@name' + cover_xpath = './/img[@class="productImage"]/@src' + title_xpath = './/h3[@class="newaps"]/a//text()' + author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()' + price_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and contains(@class, "bld")]/text()' + + for data in doc.xpath(data_xpath): + if counter <= 0: + break + + # Even though we are searching digital-text only Amazon will still + # put in results for non Kindle books (author pages). Se we need + # to explicitly check if the item is a Kindle book and ignore it + # if it isn't. + format_ = ''.join(data.xpath(format_xpath)) + if 'kindle' not in format_.lower(): + continue + + # We must have an asin otherwise we can't easily reference the + # book later. + asin = data.xpath(asin_xpath) + if asin: + asin = asin[0] + else: + continue + + cover_url = ''.join(data.xpath(cover_xpath)) + + title = ''.join(data.xpath(title_xpath)) + author = ''.join(data.xpath(author_xpath)) + try: + if self.author_article: + author = author.split(self.author_article, 1)[1].split(" (")[0] + except: + pass + + price = ''.join(data.xpath(price_xpath)) + + counter -= 1 + + s = SearchResult() + s.cover_url = cover_url.strip() + s.title = title.strip() + s.author = author.strip() + s.price = price.strip() + s.detail_item = asin.strip() + s.drm = SearchResult.DRM_UNKNOWN + s.formats = 'Kindle' + + yield s + + def get_details(self, search_result, timeout): + pass + +class AmazonESKindleStore(AmazonEUBase): ''' For comments on the implementation, please see amazon_plugin.py ''' diff --git a/src/calibre/gui2/store/stores/amazon_fr_plugin.py b/src/calibre/gui2/store/stores/amazon_fr_plugin.py index e3eff50450..22e5d8ec8e 100644 --- a/src/calibre/gui2/store/stores/amazon_fr_plugin.py +++ b/src/calibre/gui2/store/stores/amazon_fr_plugin.py @@ -8,9 +8,100 @@ __copyright__ = '2011, John Schember ' __docformat__ = 'restructuredtext en' -from calibre.gui2.store.stores.amazon_uk_plugin import AmazonUKKindleStore +from contextlib import closing +from lxml import html -class AmazonFRKindleStore(AmazonUKKindleStore): +from PyQt4.Qt import QUrl + +from calibre.gui2.store import StorePlugin +from calibre import browser +from calibre.gui2 import open_url +from calibre.gui2.store.search_result import SearchResult + + + +# This class is copy/pasted from amason_uk_plugin. Do not modify it in any +# other amazon EU plugin. Be sure to paste it into all other amazon EU plugins +# when modified. + +class AmazonEUBase(StorePlugin): + ''' + For comments on the implementation, please see amazon_plugin.py + ''' + + def open(self, parent=None, detail_item=None, external=False): + + store_link = self.store_link % self.aff_id + if detail_item: + self.aff_id['asin'] = detail_item + store_link = self.store_link_details % self.aff_id + open_url(QUrl(store_link)) + + def search(self, query, max_results=10, timeout=60): + url = self.search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+') + br = browser() + + counter = max_results + with closing(br.open(url, timeout=timeout)) as f: + doc = html.fromstring(f.read())#.decode('latin-1', 'replace')) + + data_xpath = '//div[contains(@class, "prod")]' + format_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and not(contains(@class, "bld"))]/text()' + asin_xpath = '@name' + cover_xpath = './/img[@class="productImage"]/@src' + title_xpath = './/h3[@class="newaps"]/a//text()' + author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()' + price_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and contains(@class, "bld")]/text()' + + for data in doc.xpath(data_xpath): + if counter <= 0: + break + + # Even though we are searching digital-text only Amazon will still + # put in results for non Kindle books (author pages). Se we need + # to explicitly check if the item is a Kindle book and ignore it + # if it isn't. + format_ = ''.join(data.xpath(format_xpath)) + if 'kindle' not in format_.lower(): + continue + + # We must have an asin otherwise we can't easily reference the + # book later. + asin = data.xpath(asin_xpath) + if asin: + asin = asin[0] + else: + continue + + cover_url = ''.join(data.xpath(cover_xpath)) + + title = ''.join(data.xpath(title_xpath)) + author = ''.join(data.xpath(author_xpath)) + try: + if self.author_article: + author = author.split(self.author_article, 1)[1].split(" (")[0] + except: + pass + + price = ''.join(data.xpath(price_xpath)) + + counter -= 1 + + s = SearchResult() + s.cover_url = cover_url.strip() + s.title = title.strip() + s.author = author.strip() + s.price = price.strip() + s.detail_item = asin.strip() + s.drm = SearchResult.DRM_UNKNOWN + s.formats = 'Kindle' + + yield s + + def get_details(self, search_result, timeout): + pass + +class AmazonFRKindleStore(AmazonEUBase): ''' For comments on the implementation, please see amazon_plugin.py ''' diff --git a/src/calibre/gui2/store/stores/amazon_it_plugin.py b/src/calibre/gui2/store/stores/amazon_it_plugin.py index 669831f89d..14c571e8e1 100644 --- a/src/calibre/gui2/store/stores/amazon_it_plugin.py +++ b/src/calibre/gui2/store/stores/amazon_it_plugin.py @@ -7,9 +7,100 @@ __license__ = 'GPL 3' __copyright__ = '2011, John Schember ' __docformat__ = 'restructuredtext en' -from calibre.gui2.store.stores.amazon_uk_plugin import AmazonUKKindleStore +from contextlib import closing +from lxml import html -class AmazonITKindleStore(AmazonUKKindleStore): +from PyQt4.Qt import QUrl + +from calibre.gui2.store import StorePlugin +from calibre import browser +from calibre.gui2 import open_url +from calibre.gui2.store.search_result import SearchResult + + +# This class is copy/pasted from amason_uk_plugin. Do not modify it in any +# other amazon EU plugin. Be sure to paste it into all other amazon EU plugins +# when modified. + +class AmazonEUBase(StorePlugin): + ''' + For comments on the implementation, please see amazon_plugin.py + ''' + + def open(self, parent=None, detail_item=None, external=False): + + store_link = self.store_link % self.aff_id + if detail_item: + self.aff_id['asin'] = detail_item + store_link = self.store_link_details % self.aff_id + open_url(QUrl(store_link)) + + def search(self, query, max_results=10, timeout=60): + url = self.search_url + query.encode('ascii', 'backslashreplace').replace('%', '%25').replace('\\x', '%').replace(' ', '+') + br = browser() + + counter = max_results + with closing(br.open(url, timeout=timeout)) as f: + doc = html.fromstring(f.read())#.decode('latin-1', 'replace')) + + data_xpath = '//div[contains(@class, "prod")]' + format_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and not(contains(@class, "bld"))]/text()' + asin_xpath = '@name' + cover_xpath = './/img[@class="productImage"]/@src' + title_xpath = './/h3[@class="newaps"]/a//text()' + author_xpath = './/h3[@class="newaps"]//span[contains(@class, "reg")]/text()' + price_xpath = './/ul[contains(@class, "rsltL")]//span[contains(@class, "lrg") and contains(@class, "bld")]/text()' + + for data in doc.xpath(data_xpath): + if counter <= 0: + break + + # Even though we are searching digital-text only Amazon will still + # put in results for non Kindle books (author pages). Se we need + # to explicitly check if the item is a Kindle book and ignore it + # if it isn't. + format_ = ''.join(data.xpath(format_xpath)) + if 'kindle' not in format_.lower(): + continue + + # We must have an asin otherwise we can't easily reference the + # book later. + asin = data.xpath(asin_xpath) + if asin: + asin = asin[0] + else: + continue + + cover_url = ''.join(data.xpath(cover_xpath)) + + title = ''.join(data.xpath(title_xpath)) + author = ''.join(data.xpath(author_xpath)) + try: + if self.author_article: + author = author.split(self.author_article, 1)[1].split(" (")[0] + except: + pass + + price = ''.join(data.xpath(price_xpath)) + + counter -= 1 + + s = SearchResult() + s.cover_url = cover_url.strip() + s.title = title.strip() + s.author = author.strip() + s.price = price.strip() + s.detail_item = asin.strip() + s.drm = SearchResult.DRM_UNKNOWN + s.formats = 'Kindle' + + yield s + + def get_details(self, search_result, timeout): + pass + + +class AmazonITKindleStore(AmazonEUBase): ''' For comments on the implementation, please see amazon_plugin.py ''' diff --git a/src/calibre/gui2/store/stores/amazon_uk_plugin.py b/src/calibre/gui2/store/stores/amazon_uk_plugin.py index ab67fc477c..0abc19f92e 100644 --- a/src/calibre/gui2/store/stores/amazon_uk_plugin.py +++ b/src/calibre/gui2/store/stores/amazon_uk_plugin.py @@ -17,19 +17,12 @@ from calibre.gui2 import open_url from calibre.gui2.store import StorePlugin from calibre.gui2.store.search_result import SearchResult -class AmazonUKKindleStore(StorePlugin): - aff_id = {'tag': 'calcharles-21'} - store_link = ('http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&' - 'location=http://www.amazon.co.uk/Kindle-eBooks/b?' - 'ie=UTF8&node=341689031&ref_=sa_menu_kbo2&tag=%(tag)s&' - 'linkCode=ur2&camp=1634&creative=19450') - store_link_details = ('http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&' - 'location=http://www.amazon.co.uk/dp/%(asin)s&tag=%(tag)s&' - 'linkCode=ur2&camp=1634&creative=6738') - search_url = 'http://www.amazon.co.uk/s/?url=search-alias%3Ddigital-text&field-keywords=' - author_article = 'by ' +# This class is copy/pasted from amason_uk_plugin. Do not modify it in any +# other amazon EU plugin. Be sure to paste it into all other amazon EU plugins +# when modified. +class AmazonEUBase(StorePlugin): ''' For comments on the implementation, please see amazon_plugin.py ''' @@ -105,3 +98,17 @@ class AmazonUKKindleStore(StorePlugin): def get_details(self, search_result, timeout): pass + +class AmazonUKKindleStore(AmazonEUBase): + aff_id = {'tag': 'calcharles-21'} + store_link = ('http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&' + 'location=http://www.amazon.co.uk/Kindle-eBooks/b?' + 'ie=UTF8&node=341689031&ref_=sa_menu_kbo2&tag=%(tag)s&' + 'linkCode=ur2&camp=1634&creative=19450') + store_link_details = ('http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&' + 'location=http://www.amazon.co.uk/dp/%(asin)s&tag=%(tag)s&' + 'linkCode=ur2&camp=1634&creative=6738') + search_url = 'http://www.amazon.co.uk/s/?url=search-alias%3Ddigital-text&field-keywords=' + + author_article = 'by ' + diff --git a/src/calibre/gui2/store/stores/waterstones_uk_plugin.py b/src/calibre/gui2/store/stores/waterstones_uk_plugin.py index 397b8ee53f..1bcbb865bf 100644 --- a/src/calibre/gui2/store/stores/waterstones_uk_plugin.py +++ b/src/calibre/gui2/store/stores/waterstones_uk_plugin.py @@ -41,7 +41,7 @@ class WaterstonesUKStore(BasicStoreConfig, StorePlugin): d.exec_() def search(self, query, max_results=10, timeout=60): - url = 'http://www.waterstones.com/waterstonesweb/advancedSearch.do?buttonClicked=1&format=3757&bookkeywords=' + urllib2.quote(query) + url = 'http://www.waterstones.com/waterstonesweb/simpleSearch.do?simpleSearchString=ebook+' + urllib2.quote(query) br = browser() @@ -56,6 +56,8 @@ class WaterstonesUKStore(BasicStoreConfig, StorePlugin): if not id: continue cover_url = ''.join(data.xpath('.//div[@class="image"]/a/img/@src')) + if not cover_url.startswith("http"): + cover_url = 'http://www.waterstones.com' + cover_url title = ''.join(data.xpath('./div/div/h2/a/text()')) author = ', '.join(data.xpath('.//p[@class="byAuthor"]/a/text()')) price = ''.join(data.xpath('.//p[@class="price"]/span[@class="priceRed2"]/text()'))