Python client for Scrapely browser automation service - simple, intuitive web scraping and automation
Project description
Scrapely Client
A Python client library for the Scrapely browser automation service. Scrapely provides a simple, intuitive API for web scraping and browser automation through WebSocket connections.
Installation
pip install scrapely-client
Prerequisites
Before using the Scrapely client, you must have the Scrapely service running. This client is a lightweight wrapper that connects to your self-hosted Scrapely server.
Step 1: Setup the Scrapely Service
The Scrapely service provides the browser automation backend with anti-bot capabilities. You need to deploy it first:
🔗 Clone and setup the service from: https://github.com/YahyaRehman6/scrapely
Quick setup with Docker:
# Clone the Scrapely service repository
git clone https://github.com/YahyaRehman6/scrapely.git
cd scrapely
# Build and run with Docker
docker build -t scrapely .
docker run -d \
--name scrapely-server \
-p 5050:5050 \
--restart unless-stopped \
scrapely
# Verify it's running
docker logs scrapely-server
Step 2: Install the Client
Once your Scrapely service is running, install this client package:
pip install scrapely-client
Quick Start
Basic Usage with Context Manager (Recommended)
from scrapely import Scrapely
# Connect to Scrapely service
with Scrapely("ws://localhost:5050/connect") as browser:
# Navigate to a website
browser.goto("https://example.com")
# Find and interact with elements
search_box = browser.find("#search")
search_box.type("Python web scraping")
# Click a button
browser.click("#search-button")
# Extract data
results = browser.find_all(".result-item")
for result in results:
title = result.get_text()
link = result.get_attr("href")
print(f"{title}: {link}")
Manual Connection Management
from scrapely import Scrapely
browser = Scrapely("ws://localhost:5050/connect")
browser.connect()
try:
browser.goto("https://example.com")
text = browser.get_text("h1")
print(text)
finally:
browser.close()
Core Features
Navigation
# Navigate to URL
browser.goto("https://example.com", timeout=15, wait_for_load=True)
# Wait for specific page
browser.wait_for_page("https://example.com/results")
# Get current URL
current = browser.current_url()
print(current)
Finding Elements
# Find single element
button = browser.find("#submit-btn")
# Find multiple elements
items = browser.find(".list-item", multiple=True)
# Check if element exists
if browser.exists("#optional-element"):
print("Element found!")
# Find elements within a parent
container = browser.find("#main-container")
child = container.find(".child-element")
Element Interactions
# Click elements
browser.click("#button")
button = browser.find("#button")
button.click()
# Type into input fields
browser.type("user@example.com", "#email")
browser.type("password123", "#password", clear=True)
# Scroll to element
browser.scroll_to("#footer")
element = browser.find("#section")
element.scroll_to()
Extracting Data
# Get text content
title = browser.get_text("h1")
element = browser.find(".article-title")
title = element.get_text()
# Get attributes
link = browser.get_attr("href", "a.download")
image_src = browser.find("img").get_attr("src")
data_id = browser.get_attr("data-id", ".item")
Advanced Features
JavaScript Execution
# Execute JavaScript in page context
result = browser.run_js("return document.title")
# Execute JavaScript on specific element
browser.run_js_on_element("this.style.border = '2px solid red'", "#highlight")
XPath Support
# Click element using XPath
browser.click_xpath("//button[contains(text(), 'Submit')]")
Dropdown Selection
# Select by value
browser.select_option("#country", value="us")
# Select by index
browser.select_option("#country", index=2)
Shadow DOM
# Access shadow DOM elements
shadow_root = browser.get_shadow_root("#shadow-host")
shadow_element = browser.find(element_id=shadow_root["text"])
text = shadow_element.get_text()
Drag and Drop
# Drag one element to another
browser.drag_and_drop_to(".draggable-item", ".drop-zone")
Batch Operations
Execute multiple operations efficiently in a single request:
operations = [
{
"method": "goto",
"kwargs": {"url": "https://example.com"}
},
{
"method": "type",
"kwargs": {"selector": "#email", "text": "user@example.com"}
},
{
"method": "click",
"kwargs": {"selector": "#submit"}
},
{
"method": "get_text",
"kwargs": {"selector": ".result"}
}
]
results = browser.batch_operations(operations)
for result in results:
print(f"Status: {result['status']}, Data: {result['data']}")
Complete Examples
E-commerce Scraping
with Scrapely() as browser:
browser.goto("https://shop.example.com")
# Search for products
search = browser.find("#search-input")
search.type("laptop")
browser.click("#search-button")
# Wait for results
browser.wait_for_page("https://shop.example.com/search")
# Extract product information
products = browser.find(".product-card", multiple=True)
for product in products:
name = product.find(".product-name").get_text()
price = product.find(".price").get_text()
link = product.find("a").get_attr("href")
print(f"Product: {name}")
print(f"Price: {price}")
print(f"URL: {link}")
print("-" * 40)
Form Automation
with Scrapely() as browser:
browser.goto("https://forms.example.com")
# Fill out form
browser.type("John Doe", "#name")
browser.type("john@example.com", "#email")
browser.type("555-0123", "#phone")
# Select dropdown
browser.select_option("#country", value="us")
# Check checkbox
browser.click("#terms-checkbox")
# Submit form
browser.click("#submit-button")
# Get confirmation message
message = browser.get_text(".confirmation-message")
print(message)
Dynamic Content Handling
with Scrapely() as browser:
browser.goto("https://dynamic-site.example.com")
# Scroll to load more content
for _ in range(5):
browser.scroll_to(".load-more-trigger")
time.sleep(1) # Wait for content to load
# Extract all loaded items
items = browser.find(".content-item", multiple=True)
print(f"Loaded {len(items)} items")
for item in items:
title = item.find("h2").get_text()
description = item.find(".description").get_text()
print(f"{title}: {description}")
Configuration
Custom WebSocket URL
# Connect to custom service URL
browser = Scrapely("ws://192.168.1.100:8080/connect")
Connection Timeout
# Set custom connection timeout (in seconds)
browser = Scrapely("ws://localhost:5050/connect", timeout=60)
Error Handling
from scrapely import Scrapely, ConnectionError, OperationError
try:
with Scrapely() as browser:
browser.goto("https://example.com")
browser.click("#non-existent-button")
except ConnectionError as e:
print(f"Failed to connect: {e}")
except OperationError as e:
print(f"Operation failed: {e}")
API Reference
Scrapely Class
Connection Methods
connect()- Establish WebSocket connectionclose()- Close connection and cleanup
Navigation Methods
goto(url, timeout, wait_for_load)- Navigate to URLwait_for_page(url, timeout)- Wait for page URL to matchcurrent_url()- Get current page URL
Element Finding Methods
find(selector, element_id, timeout, multiple)- Find element(s)exists(selector, element_id)- Check if element exists
Interaction Methods
click(selector, element_id, timeout)- Click elementtype(text, selector, element_id, timeout, clear)- Type textscroll_to(selector, element_id, timeout)- Scroll to element
Data Extraction Methods
get_text(selector, element_id, timeout)- Get element textget_attr(attribute, selector, element_id, timeout)- Get attribute value
Advanced Methods
run_js(script, *args)- Execute JavaScriptrun_js_on_element(script, selector, element_id, timeout)- Execute JS on elementclick_xpath(xpath)- Click using XPathselect_option(selector, index, value, timeout)- Select dropdown optionget_shadow_root(selector, element_id, timeout)- Access shadow DOMdrag_and_drop_to(draggable, droppable, timeout)- Drag and drop
Batch Methods
batch_operations(operations)- Execute multiple operations
Element Class
Element objects support chainable method calls:
click(timeout)- Click this elementtype(text, timeout, clear)- Type into this elementget_text(timeout)- Get text contentget_attr(attribute, timeout)- Get attribute valuescroll_to(timeout)- Scroll to this elementrun_js(script, timeout)- Execute JavaScript on this elementexists(timeout)- Check if element still existsfind(selector, timeout)- Find child elementfind_all(selector, timeout)- Find all child elements
Requirements
- Python 3.7+
- websocket-client
- Running Scrapely service instance
License
Apache License
Support
For issues, questions, or contributions, please visit the project repository.
Changelog
Version 1.0.0
- Initial release
- Core browser automation features
- Element caching and chaining
- Batch operations support
- Shadow DOM support
- Drag and drop functionality
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scrapely_client-1.0.1.tar.gz.
File metadata
- Download URL: scrapely_client-1.0.1.tar.gz
- Upload date:
- Size: 16.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c68bcfda562ac2091d1118748c53c1716924a005570970b87af02efd6d94c6fc
|
|
| MD5 |
00c65faa8ddd32d4ea243f0c1e94b987
|
|
| BLAKE2b-256 |
1eafc2a00970bb30da6614229d1517cde59fee00ac9317d5881e20b7c11d4e8a
|
File details
Details for the file scrapely_client-1.0.1-py3-none-any.whl.
File metadata
- Download URL: scrapely_client-1.0.1-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cdeeaa6d358691b6c5aac467995acc61b25d208b77e6ab24a5903af66d82048e
|
|
| MD5 |
9e66a8ff9caec902c9710c92c1a61553
|
|
| BLAKE2b-256 |
e70253d893f38603f4da6fffd8405d6991669b41571b3844e1f9772560f3c019
|