Adding css_first and xpath_first for easier usage
This commit is contained in:
@@ -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
|
quotes = [element.text for element in page.css('.quote').css('.text')] # Slower than bulk query above
|
||||||
|
|
||||||
# Get the first quote element
|
# 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
|
# Working with elements
|
||||||
quote.html_content # Inner HTML
|
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
|
```python
|
||||||
>>> for product in page.find_by_text('Tipping the Velvet').parent.parent.find_similar():
|
>>> for product in page.find_by_text('Tipping the Velvet').parent.parent.find_similar():
|
||||||
print({
|
print({
|
||||||
"name": product.css('h3 a::text')[0],
|
"name": product.css_first('h3 a::text'),
|
||||||
"price": product.css('.price_color')[0].re_first(r'[\d\.]+'),
|
"price": product.css_first('.price_color').re_first(r'[\d\.]+'),
|
||||||
"stock": product.css('.availability::text')[-1].clean()
|
"stock": product.css('.availability::text')[-1].clean()
|
||||||
})
|
})
|
||||||
{'name': 'A Light in the ...', 'price': '51.77', 'stock': 'In stock'}
|
{'name': 'A Light in the ...', 'price': '51.77', 'stock': 'In stock'}
|
||||||
|
|||||||
@@ -394,6 +394,58 @@ class Adaptor(SelectorsGeneration):
|
|||||||
return self.__convert_results(score_table[highest_probability])
|
return self.__convert_results(score_table[highest_probability])
|
||||||
return []
|
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 = '',
|
def css(self, selector: str, identifier: str = '',
|
||||||
auto_match: bool = False, auto_save: bool = False, percentage: int = 0
|
auto_match: bool = False, auto_save: bool = False, percentage: int = 0
|
||||||
) -> Union['Adaptors[Adaptor]', List]:
|
) -> Union['Adaptors[Adaptor]', List]:
|
||||||
|
|||||||
Reference in New Issue
Block a user