Listing Pilot: Mobile Automation Suite for C2C Marketplaces
A platform-agnostic, config-driven mobile automation suite built with Python and Appium, designed to manage over 1,000 active listings across Turkish C2C marketplaces using coordinate-based pairing and overlap detection algorithms.
Overview
For individual merchants and collectibles micro-ventures, Turkey’s top C2C marketplaces (such as Dolap and Gardrops) are highly lucrative. However, their mobile-first designs require sellers to spend hours performing repetitive manual listing updates, pricing adjustments, and inventory synchronization on physical mobile devices.
To eliminate this overhead, I engineered Listing Pilot, a platform-agnostic, config-driven mobile automation suite. Built in Python using Appium, it automates the management of ~1,000 active listings, translating hours of manual weekly operations into automated, reliable background scripts.
Results at a Glance
| Metric | Manual Process | Listing Pilot (Automated) | Optimization |
|---|---|---|---|
| Workflow Duration | 4–5 hours / week | ~15 minutes (Background) | 95% Time Saved |
| Listing Capacity | Limit of ~200 items | 1,000+ active listings | 5x Scale Increase |
| Sync Frequency | Once daily (Manual) | Multi-interval schedules | Retraining-Free sync |
| Alerting | Manual check | Immediate Telegram notification | Proactive error response |
Phase 1: Architecture — Platform-Agnostic Engine
The primary engineering challenge in mobile app automation is fragility. App updates change UI IDs, screen ratios vary across devices, and running the same script on two different models can cause it to fail.
To overcome this, Listing Pilot separates the automation script logic from specific app selectors and hardware specifications.
flowchart TD
Config[JSON Configuration Profile] --> Loader[Selector & Capability Loader]
Loader --> Engine[Appium Automation Core]
Engine --> AppiumServer[Local Appium Server]
AppiumServer --> Device[Android/iOS Emulator or Physical Phone]
Engine --> ErrorLogger[Multi-ID Selector Fallback]
Engine --> Telegram[Telegram Bot Client]
JSON Profile Injection
All locators (XPaths, IDs, coordinates) are defined in external profiles. If a marketplace changes its layout, we simply update the JSON schema without modifying the underlying Python code.
1
2
3
4
5
6
7
8
9
{
"platform": "Android",
"app_package": "com.c2c.marketplace",
"locators": {
"listing_card": "//android.widget.FrameLayout[@resource-id='com.c2c:id/card']",
"edit_btn": "com.c2c:id/btn_edit",
"submit_btn": "com.c2c:id/btn_save"
}
}
Phase 2: Advanced Interaction Algorithms
Mobile layouts often lack clean semantic structure. Elements like item titles, prices, and edit buttons are frequently sibling nodes in the view tree, making it difficult to link them using standard relative selectors.
Listing Pilot uses spatial algorithms to navigate these complex layouts.
1. Spatial Title-to-Price Pairing
To edit an item, the script must match its title text to the corresponding edit button on the same card. Listing Pilot fetches the bounding boxes (coordinates) of all visible titles and edit buttons, then pairs them using a distance-matching algorithm:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def pair_elements_by_coordinates(titles, edit_buttons):
pairs = {}
for title in titles:
t_box = title.rect # Contains x, y, width, height
t_center_y = t_box['y'] + (t_box['height'] / 2)
# Find the edit button closest in vertical alignment (closest Y center)
closest_btn = min(
edit_buttons,
key=lambda btn: abs((btn.rect['y'] + btn.rect['height']/2) - t_center_y)
)
# Verify the button is on the same row (horizontal boundary)
if abs((closest_btn.rect['y'] + closest_btn.rect['height']/2) - t_center_y) < 100:
pairs[title.text] = closest_btn
return pairs
2. Sticky-Element Overlap Detection
Marketing banners, support widgets, or cookies warnings often load asynchronously and cover key buttons. If Appium attempts to click an element obscured by an overlay, it will fail or click the wrong button.
Listing Pilot inspects element bounding boxes prior to execution:
\[\text{Overlap} = (X_{1,\text{min}} < X_{2,\text{max}}) \land (X_{1,\text{max}} > X_{2,\text{min}}) \land (Y_{1,\text{min}} < Y_{2,\text{max}}) \land (Y_{1,\text{max}} > Y_{2,\text{min}})\]If an overlap is detected, the script automatically triggers a dismissal function for the sticky overlay before proceeding.
Phase 3: Fault-Tolerant Operations
Mobile environments are unstable. Network hiccups, sudden popups, or application crashes can disrupt automation runs. Listing Pilot implements two main recovery strategies:
- Multi-ID Fallback Selector Strategy: When searching for a UI element, the framework checks a prioritized list of selectors (e.g.,
resource-idfirst, thencontent-desc, and finally a calculated coordinate-relative click if the node isn’t found). - Dynamic Sleep Auto-tuning: The runner tracks average response latency. If API requests take longer to load due to network throttling, it automatically scales up the wait time between navigation steps (from a default 1.5s up to 5.0s) to prevent timeouts.
Phase 4: Real-time Telemetry & Telegram Alerts
Since Listing Pilot runs as a background process on a local server, keeping track of its status is crucial. The suite integrates directly with the Telegram Bot API to send updates to the operator.
The system reports:
- Session Startup: Details on the device ID and the target marketplace.
- Progress Milestones: Sends a message every 100 listings processed.
- Screenshots on Failure: If a step fails, Listing Pilot captures a screenshot, highlights the area where the button was expected using OpenCV, and sends it directly to Telegram for quick troubleshooting.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def send_telegram_alert(message, image_path=None):
bot_token = os.getenv("TELEGRAM_BOT_TOKEN")
chat_id = os.getenv("TELEGRAM_CHAT_ID")
if image_path:
with open(image_path, 'rb') as photo:
requests.post(
f"https://api.telegram.org/bot{bot_token}/sendPhoto",
data={"chat_id": chat_id, "caption": message},
files={"photo": photo}
)
else:
requests.post(
f"https://api.telegram.org/bot{bot_token}/sendMessage",
json={"chat_id": chat_id, "text": message}
)
Listing Pilot has transformed C2C merchant operations from a manual chore into a highly scalable, automated business workflow.