clawdbot-workspace/reonomy-selectors-explore.js

238 lines
8.7 KiB
JavaScript

const { chromium } = require('/Users/jakeshore/ClawdBot/node_modules/playwright');
(async () => {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
console.log('Navigating to Reonomy...');
await page.goto('https://app.reonomy.com');
// Wait for login form
await page.waitForSelector('input[placeholder="yours@example.com"]', { timeout: 10000 });
console.log('Filling in credentials...');
await page.fill('input[placeholder="yours@example.com"]', 'henry@realestateenhanced.com');
await page.fill('input[placeholder="your password"]', '9082166532');
console.log('Clicking login...');
await page.click('button:has-text("Log In")');
// Wait for navigation
await page.waitForLoadState('networkidle', { timeout: 15000 });
console.log('Current URL:', page.url());
// Try to navigate to a property detail page directly
const propertyIds = [
'710c31f7-5021-5494-b43e-92f03882759b',
'89ad58c3-39c7-5ecb-8a30-58ec6c28fc1a'
];
for (const propId of propertyIds) {
console.log(`\n\n=== Analyzing property: ${propId} ===`);
const propertyUrl = `https://app.reonomy.com/#!/property/${propId}`;
console.log(`Navigating to: ${propertyUrl}`);
await page.goto(propertyUrl);
await page.waitForLoadState('networkidle', { timeout: 15000 });
await page.waitForTimeout(3000); // Extra wait for dynamic content
// Save screenshot
const screenshotPath = `/Users/jakeshore/.clawdbot/workspace/property-${propId}.png`;
await page.screenshot({ path: screenshotPath, fullPage: true });
console.log('Screenshot saved:', screenshotPath);
// Extract page HTML structure for analysis
console.log('\n=== SEARCHING FOR EMAIL/PHONE ELEMENTS ===\n');
// Search for specific patterns
const patterns = await page.evaluate(() => {
const results = [];
// Look for elements with text matching email pattern
const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/;
const phoneRegex = /\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})/;
// Check all elements
const allElements = document.querySelectorAll('*');
allElements.forEach(el => {
const text = el.textContent?.trim() || '';
const href = el.getAttribute('href') || '';
// Check if this element contains an email
if (emailRegex.test(text) || href.startsWith('mailto:')) {
results.push({
type: 'email',
tag: el.tagName,
class: el.className,
id: el.id,
text: text.substring(0, 100),
href: href.substring(0, 100),
html: el.outerHTML.substring(0, 300),
parentClass: el.parentElement?.className || '',
parentTag: el.parentElement?.tagName || '',
selectors: [
el.id ? `#${el.id}` : null,
el.className ? `.${el.className.split(' ')[0]}` : null,
`${el.tagName.toLowerCase()}[class*="${el.className.split(' ')[0] || ''}"]`,
].filter(Boolean)
});
}
// Check if this element contains a phone
if (phoneRegex.test(text) || href.startsWith('tel:')) {
results.push({
type: 'phone',
tag: el.tagName,
class: el.className,
id: el.id,
text: text.substring(0, 100),
href: href.substring(0, 100),
html: el.outerHTML.substring(0, 300),
parentClass: el.parentElement?.className || '',
parentTag: el.parentElement?.tagName || '',
selectors: [
el.id ? `#${el.id}` : null,
el.className ? `.${el.className.split(' ')[0]}` : null,
`${el.tagName.toLowerCase()}[class*="${el.className.split(' ')[0] || ''}"]`,
].filter(Boolean)
});
}
});
return results;
});
// Print results
if (patterns.length === 0) {
console.log('No email/phone elements found with regex pattern matching.');
console.log('\n=== LOOKING FOR "EMAIL" AND "PHONE" LABELS ===\n');
const labeledElements = await page.evaluate(() => {
const results = [];
const allElements = document.querySelectorAll('*');
allElements.forEach(el => {
const text = el.textContent?.trim() || '';
const lowerText = text.toLowerCase();
// Look for elements that might be labels
if (lowerText === 'email' || lowerText === 'e-mail' || lowerText === 'phone' ||
lowerText === 'telephone' || lowerText === 'tel') {
// Check the next sibling or children for the actual value
const nextSibling = el.nextElementSibling;
const children = el.parentElement?.querySelectorAll(el.tagName === 'SPAN' ? '*' : `${el.tagName} + *`);
results.push({
labelText: text,
labelClass: el.className,
labelId: el.id,
nextSiblingText: nextSibling?.textContent?.trim()?.substring(0, 100) || '',
nextSiblingClass: nextSibling?.className || '',
nextSiblingTag: nextSibling?.tagName || '',
parentHTML: el.parentElement?.outerHTML?.substring(0, 500) || ''
});
}
});
return results;
});
console.log('Labeled elements:', JSON.stringify(labeledElements, null, 2));
} else {
console.log(`Found ${patterns.length} potential email/phone elements:\n`);
// Group by type
const emails = patterns.filter(p => p.type === 'email');
const phones = patterns.filter(p => p.type === 'phone');
console.log('EMAIL ELEMENTS:');
emails.slice(0, 5).forEach((item, i) => {
console.log(`\n${i + 1}. Tag: ${item.tag}`);
console.log(` Class: ${item.class}`);
console.log(` ID: ${item.id}`);
console.log(` Text: ${item.text}`);
console.log(` Parent Tag: ${item.parentTag}`);
console.log(` Parent Class: ${item.parentClass}`);
console.log(` Suggested Selectors:`);
item.selectors.forEach(sel => console.log(` - ${sel}`));
});
console.log('\n\nPHONE ELEMENTS:');
phones.slice(0, 5).forEach((item, i) => {
console.log(`\n${i + 1}. Tag: ${item.tag}`);
console.log(` Class: ${item.class}`);
console.log(` ID: ${item.id}`);
console.log(` Text: ${item.text}`);
console.log(` Parent Tag: ${item.parentTag}`);
console.log(` Parent Class: ${item.parentClass}`);
console.log(` Suggested Selectors:`);
item.selectors.forEach(sel => console.log(` - ${sel}`));
});
}
// Also check for data-* attributes
console.log('\n\n=== CHECKING FOR DATA-* ATTRIBUTES ===\n');
const dataAttributes = await page.evaluate(() => {
const results = [];
const allElements = document.querySelectorAll('*');
allElements.forEach(el => {
// Check all data attributes
Array.from(el.attributes).forEach(attr => {
if (attr.name.startsWith('data-')) {
const name = attr.name.toLowerCase();
if (name.includes('email') || name.includes('phone') || name.includes('contact') ||
name.includes('mail') || name.includes('tel')) {
results.push({
attribute: attr.name,
value: attr.value,
tag: el.tagName,
class: el.className,
text: el.textContent?.trim()?.substring(0, 50) || ''
});
}
}
});
});
return results;
});
if (dataAttributes.length > 0) {
console.log(`Found ${dataAttributes.length} elements with relevant data attributes:\n`);
dataAttributes.forEach((item, i) => {
console.log(`${i + 1}. ${item.attribute}="${item.value}"`);
console.log(` Tag: ${item.tag}, Class: ${item.class}`);
console.log(` Text: ${item.text}\n`);
});
} else {
console.log('No data attributes found containing email/phone/contact keywords.');
}
// Save detailed analysis to JSON
const analysis = {
propertyId: propId,
url: propertyUrl,
emailPhoneElements: patterns,
labeledElements: [],
dataAttributes: dataAttributes
};
const fs = require('fs');
fs.writeFileSync(
`/Users/jakeshore/.clawdbot/workspace/property-${propId}-analysis.json`,
JSON.stringify(analysis, null, 2)
);
console.log(`\nAnalysis saved to: property-${propId}-analysis.json`);
}
console.log('\n\n=== DONE ===');
console.log('Keeping browser open for 60 seconds for manual inspection...');
await page.waitForTimeout(60000);
await browser.close();
console.log('Browser closed.');
})();