mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-09-22 02:46:39 +00:00
* fix(oxylabs): report scrape failures instead of raising IndexError
The oxylabs SDK logs HTTP errors and returns an empty response rather than
raising, so the unchecked `response.results[0]` in every Oxylabs tool turned a
rejected request into `IndexError: list index out of range`. Invalid credentials
-- the most likely first-run mistake -- gave no indication of the cause. A
result carrying a non-2xx `status_code` had the same problem one level down: the
job ran, the page did not come back, and the tool returned its empty content as
though the scrape had succeeded, handing the agent "[]".
Both are now reported as a `ToolFailure` naming what went wrong, so the agent
gets something it can act on and the framework records the call as failed:
401 Unauthorized
400 Bad Request - Parameter `parsing_instructions` can be used just with
`parse` parameter set to `true`.
Because the SDK keeps the cause only in its own log, the failing call is run
with a handler attached to the `oxylabs` logger and the status, the API's
explanation and timeouts are read back off it. `code` and `retryable` are set
from the status, so 429 and 5xx are marked worth retrying. Nothing about the
caller's logging configuration is changed; an application that has silenced the
SDK still gets the generic failure.
Content that is neither a string nor a dict is also serialized properly:
`parsing_instructions` commonly yields a list, and the previous `str()`
fallback produced a Python repr with single quotes instead of JSON.
The client construction and response handling these four tools duplicated
verbatim now live in a shared `OxylabsBaseTool`, following the existing
`SerpApiBaseTool` pattern, so the handling above exists in one place. The
generated tool specs change only by the new `locale` field, confirming the
tools' public surface is otherwise untouched.
Also add the `locale` option to the Google Search config, which the docs
already documented but the config model silently dropped, and correct two
copy-paste errors in the docs across all four locales.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(oxylabs): keep concurrent scrape diagnoses apart
The error capture attached a fresh handler to the shared `oxylabs` logger for
each scrape, so two scrapes in flight at once each saw both errors. `_diagnose`
reads the first HTTP status it finds, so a timeout could be reported as the
other request's 400 -- `retryable=False` on a failure that was worth retrying.
One handler now serves every scrape and routes each record to the capture of
the call that caused it via a `ContextVar`, which isolates threads and asyncio
tasks alike. Serializing the captures would have fixed the cross-talk too, but
at the cost of running every scrape one at a time. The handler stays attached
once installed: it is inert outside a capture, and detaching it would race with
concurrent scrapes.
The regression test forces the interleaving -- one capture is held open while
the other call logs -- and fails against the previous implementation.
Also drive `config` through the public constructor in the tests instead of
assigning `__dict__["config"]`, so they would catch `__init__` dropping a
supplied config.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
238 lines
6.7 KiB
Plaintext
238 lines
6.7 KiB
Plaintext
---
|
|
title: Oxylabs Scrapers
|
|
description: >
|
|
Oxylabs Scrapers allow to easily access the information from the respective sources. Please see the list of available sources below:
|
|
- `Amazon Product`
|
|
- `Amazon Search`
|
|
- `Google Search`
|
|
- `Universal`
|
|
icon: globe
|
|
mode: "wide"
|
|
---
|
|
|
|
## Installation
|
|
|
|
Get the credentials by creating an Oxylabs Account [here](https://oxylabs.io).
|
|
```shell
|
|
pip install 'crewai[tools]' oxylabs
|
|
```
|
|
Check [Oxylabs Documentation](https://developers.oxylabs.io/scraping-solutions/web-scraper-api/targets) to get more information about API parameters.
|
|
|
|
# `OxylabsAmazonProductScraperTool`
|
|
|
|
### Example
|
|
|
|
```python
|
|
from crewai_tools import OxylabsAmazonProductScraperTool
|
|
|
|
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
|
|
tool = OxylabsAmazonProductScraperTool()
|
|
|
|
result = tool.run(query="AAAAABBBBCC")
|
|
|
|
print(result)
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- `query` - 10-symbol ASIN code.
|
|
- `domain` - domain localization for Amazon.
|
|
- `geo_location` - the _Deliver to_ location.
|
|
- `user_agent_type` - device type and browser.
|
|
- `render` - enables JavaScript rendering when set to `html`.
|
|
- `callback_url` - URL to your callback endpoint.
|
|
- `context` - Additional advanced settings and controls for specialized requirements.
|
|
- `parse` - returns parsed data when set to true.
|
|
- `parsing_instructions` - define your own parsing and data transformation logic that will be executed on an HTML scraping result.
|
|
|
|
### Advanced example
|
|
|
|
```python
|
|
from crewai_tools import OxylabsAmazonProductScraperTool
|
|
|
|
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
|
|
tool = OxylabsAmazonProductScraperTool(
|
|
config={
|
|
"domain": "com",
|
|
"parse": True,
|
|
"context": [
|
|
{
|
|
"key": "autoselect_variant",
|
|
"value": True
|
|
}
|
|
]
|
|
}
|
|
)
|
|
|
|
result = tool.run(query="AAAAABBBBCC")
|
|
|
|
print(result)
|
|
```
|
|
|
|
# `OxylabsAmazonSearchScraperTool`
|
|
|
|
### Example
|
|
|
|
```python
|
|
from crewai_tools import OxylabsAmazonSearchScraperTool
|
|
|
|
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
|
|
tool = OxylabsAmazonSearchScraperTool()
|
|
|
|
result = tool.run(query="headsets")
|
|
|
|
print(result)
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- `query` - Amazon search term.
|
|
- `domain` - domain localization for Amazon.
|
|
- `start_page` - starting page number.
|
|
- `pages` - number of pages to retrieve.
|
|
- `geo_location` - the _Deliver to_ location.
|
|
- `user_agent_type` - device type and browser.
|
|
- `render` - enables JavaScript rendering when set to `html`.
|
|
- `callback_url` - URL to your callback endpoint.
|
|
- `context` - Additional advanced settings and controls for specialized requirements.
|
|
- `parse` - returns parsed data when set to true.
|
|
- `parsing_instructions` - define your own parsing and data transformation logic that will be executed on an HTML scraping result.
|
|
|
|
### Advanced example
|
|
|
|
```python
|
|
from crewai_tools import OxylabsAmazonSearchScraperTool
|
|
|
|
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
|
|
tool = OxylabsAmazonSearchScraperTool(
|
|
config={
|
|
"domain": 'nl',
|
|
"start_page": 2,
|
|
"pages": 2,
|
|
"parse": True,
|
|
"context": [
|
|
{'key': 'category_id', 'value': 16391693031}
|
|
],
|
|
}
|
|
)
|
|
|
|
result = tool.run(query='nirvana tshirt')
|
|
|
|
print(result)
|
|
```
|
|
|
|
# `OxylabsGoogleSearchScraperTool`
|
|
|
|
### Example
|
|
|
|
```python
|
|
from crewai_tools import OxylabsGoogleSearchScraperTool
|
|
|
|
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
|
|
tool = OxylabsGoogleSearchScraperTool()
|
|
|
|
result = tool.run(query="iPhone 16")
|
|
|
|
print(result)
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- `query` - search keyword.
|
|
- `domain` - domain localization for Google.
|
|
- `start_page` - starting page number.
|
|
- `pages` - number of pages to retrieve.
|
|
- `limit` - number of results to retrieve in each page.
|
|
- `locale` - `Accept-Language` header value which changes your Google search page web interface language.
|
|
- `geo_location` - the geographical location that the result should be adapted for. Using this parameter correctly is extremely important to get the right data.
|
|
- `user_agent_type` - device type and browser.
|
|
- `render` - enables JavaScript rendering when set to `html`.
|
|
- `callback_url` - URL to your callback endpoint.
|
|
- `context` - Additional advanced settings and controls for specialized requirements.
|
|
- `parse` - returns parsed data when set to true.
|
|
- `parsing_instructions` - define your own parsing and data transformation logic that will be executed on an HTML scraping result.
|
|
|
|
### Advanced example
|
|
|
|
```python
|
|
from crewai_tools import OxylabsGoogleSearchScraperTool
|
|
|
|
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
|
|
tool = OxylabsGoogleSearchScraperTool(
|
|
config={
|
|
"parse": True,
|
|
"geo_location": "Paris, France",
|
|
"user_agent_type": "tablet",
|
|
}
|
|
)
|
|
|
|
result = tool.run(query="iPhone 16")
|
|
|
|
print(result)
|
|
```
|
|
|
|
# `OxylabsUniversalScraperTool`
|
|
|
|
### Example
|
|
|
|
```python
|
|
from crewai_tools import OxylabsUniversalScraperTool
|
|
|
|
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
|
|
tool = OxylabsUniversalScraperTool()
|
|
|
|
result = tool.run(url="https://ip.oxylabs.io")
|
|
|
|
print(result)
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- `url` - website url to scrape.
|
|
- `user_agent_type` - device type and browser.
|
|
- `geo_location` - sets the proxy's geolocation to retrieve data.
|
|
- `render` - enables JavaScript rendering when set to `html`.
|
|
- `callback_url` - URL to your callback endpoint.
|
|
- `context` - Additional advanced settings and controls for specialized requirements.
|
|
- `parse` - returns parsed data when set to `true`, as long as a dedicated parser exists for the submitted URL's page type.
|
|
- `parsing_instructions` - define your own parsing and data transformation logic that will be executed on an HTML scraping result.
|
|
|
|
|
|
### Advanced example
|
|
|
|
```python
|
|
from crewai_tools import OxylabsUniversalScraperTool
|
|
|
|
# make sure OXYLABS_USERNAME and OXYLABS_PASSWORD variables are set
|
|
tool = OxylabsUniversalScraperTool(
|
|
config={
|
|
"render": "html",
|
|
"user_agent_type": "mobile",
|
|
"context": [
|
|
{"key": "force_headers", "value": True},
|
|
{"key": "force_cookies", "value": True},
|
|
{
|
|
"key": "headers",
|
|
"value": {
|
|
"Custom-Header-Name": "custom header content",
|
|
},
|
|
},
|
|
{
|
|
"key": "cookies",
|
|
"value": [
|
|
{"key": "NID", "value": "1234567890"},
|
|
{"key": "1P JAR", "value": "0987654321"},
|
|
],
|
|
},
|
|
{"key": "http_method", "value": "get"},
|
|
{"key": "follow_redirects", "value": True},
|
|
{"key": "successful_status_codes", "value": [808, 909]},
|
|
],
|
|
}
|
|
)
|
|
|
|
result = tool.run(url="https://ip.oxylabs.io")
|
|
|
|
print(result)
|
|
```
|