Adding css_first and xpath_first for easier usage

This commit is contained in:
Karim shoair
2024-11-05 23:41:51 +02:00
parent 009c2914aa
commit 3622040440
2 changed files with 55 additions and 3 deletions
+3 -3
View File
@@ -59,7 +59,7 @@ quotes = page.css('.quote').css('.text::text') # Chained selectors
quotes = [element.text for element in page.css('.quote').css('.text')] # Slower than bulk query above
# Get the first quote element
quote = page.css('.quote').first # or [0] or .get()
quote = page.css_first('.quote') # or page.css('.quote').first or [0] or .get()
# Working with elements
quote.html_content # Inner HTML
@@ -244,8 +244,8 @@ To increase the complexity a little bit, let's say we want to get all books' dat
```python
>>> for product in page.find_by_text('Tipping the Velvet').parent.parent.find_similar():
print({
"name": product.css('h3 a::text')[0],
"price": product.css('.price_color')[0].re_first(r'[\d\.]+'),
"name": product.css_first('h3 a::text'),
"price": product.css_first('.price_color').re_first(r'[\d\.]+'),
"stock": product.css('.availability::text')[-1].clean()
})
{'name': 'A Light in the ...', 'price': '51.77', 'stock': 'In stock'}
+52
View File
@@ -394,6 +394,58 @@ class Adaptor(SelectorsGeneration):
return self.__convert_results(score_table[highest_probability])
return []
def css_first(self, selector: str, identifier: str = '',
auto_match: bool = False, auto_save: bool = False, percentage: int = 0
) -> Union['Adaptors[Adaptor]', List, None]:
"""Search current tree with CSS3 selectors and return the first result if possible, otherwise return `None`
**Important:
It's recommended to use the identifier argument if you plan to use different selector later
and want to relocate the same element(s)**
:param selector: The CSS3 selector to be used.
:param auto_match: Enabled will make function try to relocate the element if it was 'saved' before
:param identifier: A string that will be used to save/retrieve element's data in auto-matching
otherwise the selector will be used.
:param auto_save: Automatically save new elements for `auto_match` later
:param percentage: The minimum percentage to accept while auto-matching and not going lower than that.
Be aware that the percentage calculation depends solely on the page structure so don't play with this
number unless you must know what you are doing!
:return: List as :class:`Adaptors`
"""
try:
return self.css(selector, identifier, auto_match, auto_save, percentage)[0]
except (IndexError, TypeError,):
return None
def xpath_first(self, selector: str, identifier: str = '',
auto_match: bool = False, auto_save: bool = False, percentage: int = 0, **kwargs: Any
) -> Union['Adaptors[Adaptor]', List, None]:
"""Search current tree with XPath selectors and return the first result if possible, otherwise return `None`
**Important:
It's recommended to use the identifier argument if you plan to use different selector later
and want to relocate the same element(s)**
Note: **Additional keyword arguments will be passed as XPath variables in the XPath expression!**
:param selector: The XPath selector to be used.
:param auto_match: Enabled will make function try to relocate the element if it was 'saved' before
:param identifier: A string that will be used to save/retrieve element's data in auto-matching
otherwise the selector will be used.
:param auto_save: Automatically save new elements for `auto_match` later
:param percentage: The minimum percentage to accept while auto-matching and not going lower than that.
Be aware that the percentage calculation depends solely on the page structure so don't play with this
number unless you must know what you are doing!
:return: List as :class:`Adaptors`
"""
try:
return self.xpath(selector, identifier, auto_match, auto_save, percentage, **kwargs)[0]
except (IndexError, TypeError,):
return None
def css(self, selector: str, identifier: str = '',
auto_match: bool = False, auto_save: bool = False, percentage: int = 0
) -> Union['Adaptors[Adaptor]', List]: