initial commit
This commit is contained in:
commit
be92c28c55
6
content.js
Normal file
6
content.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
window.addEventListener("message", (event) => {
|
||||||
|
if (event.source !== window) return;
|
||||||
|
if (event.data?.type === "FROM_INJECTED") {
|
||||||
|
chrome.runtime.sendMessage({ type: "PRODUCT_DATA", data: event.data.data });
|
||||||
|
}
|
||||||
|
});
|
||||||
9
icon.svg
Normal file
9
icon.svg
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-11.5 -10.23174 23 20.46348">
|
||||||
|
<title>React Logo</title>
|
||||||
|
<circle cx="0" cy="0" r="2.05" fill="#61dafb"/>
|
||||||
|
<g stroke="#61dafb" stroke-width="1" fill="none">
|
||||||
|
<ellipse rx="11" ry="4.2"/>
|
||||||
|
<ellipse rx="11" ry="4.2" transform="rotate(60)"/>
|
||||||
|
<ellipse rx="11" ry="4.2" transform="rotate(120)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 366 B |
35
inject.js
Normal file
35
inject.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
(function () {
|
||||||
|
const waitForRunParams = (timeout = 5000) => {
|
||||||
|
return new Promise((res) => {
|
||||||
|
const start = Date.now();
|
||||||
|
const check = () => {
|
||||||
|
if (window.runParams && Object.keys(window.runParams).length > 0) {
|
||||||
|
return res(window.runParams);
|
||||||
|
}
|
||||||
|
if (Date.now() - start > timeout) return res(null);
|
||||||
|
requestAnimationFrame(check);
|
||||||
|
};
|
||||||
|
check();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const runParams = await waitForRunParams();
|
||||||
|
const result = {
|
||||||
|
title: document.querySelector('[data-pl="product-title"]')?.innerText || '',
|
||||||
|
images: runParams?.imageModule?.imagePathList || [],
|
||||||
|
specs: {},
|
||||||
|
description: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
const specsData = runParams?.specifications || runParams?.productInfoComponent?.specifications || [];
|
||||||
|
specsData.forEach(group => {
|
||||||
|
(group.attributes || []).forEach(attr => {
|
||||||
|
result.specs[attr.attrName] = attr.attrValue;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// שלח חזרה לתוסף
|
||||||
|
window.postMessage({ type: 'FROM_INJECTED', data: result }, '*');
|
||||||
|
})();
|
||||||
|
})();
|
||||||
24
manifest.json
Normal file
24
manifest.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"name": "AliExpress Scraper",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "Extract product data from AliExpress into JSON.",
|
||||||
|
"permissions": ["scripting", "activeTab"],
|
||||||
|
"action": {
|
||||||
|
"default_popup": "popup.html",
|
||||||
|
"default_icon": "icon.svg"
|
||||||
|
},
|
||||||
|
"content_scripts": [
|
||||||
|
{
|
||||||
|
"matches": ["*://*.aliexpress.com/item/*"],
|
||||||
|
"js": ["content.js"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"host_permissions": ["*://*.aliexpress.com/*"],
|
||||||
|
"web_accessible_resources": [
|
||||||
|
{
|
||||||
|
"resources": ["inject.js"],
|
||||||
|
"matches": ["<all_urls>"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
17
popup.html
Normal file
17
popup.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>AliExpress Scraper</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: sans-serif; padding: 10px; }
|
||||||
|
pre { max-height: 300px; overflow-y: auto; background: #f0f0f0; padding: 10px; }
|
||||||
|
button { margin-top: 10px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>AliExpress Product JSON</h3>
|
||||||
|
<pre id="output">Loading...</pre>
|
||||||
|
<button id="copyBtn">Copy to Clipboard</button>
|
||||||
|
<script src="popup.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
31
popup.js
Normal file
31
popup.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
|
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||||
|
|
||||||
|
// Inject inject.js into page
|
||||||
|
chrome.scripting.executeScript({
|
||||||
|
target: { tabId: tab.id },
|
||||||
|
func: () => {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.src = chrome.runtime.getURL("inject.js");
|
||||||
|
document.documentElement.appendChild(script);
|
||||||
|
script.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for content.js to relay message from injected script
|
||||||
|
chrome.runtime.onMessage.addListener(function listener(message) {
|
||||||
|
if (message?.type === "PRODUCT_DATA") {
|
||||||
|
const data = message.data;
|
||||||
|
|
||||||
|
const output = document.getElementById("output");
|
||||||
|
output.textContent = JSON.stringify(data, null, 2);
|
||||||
|
|
||||||
|
document.getElementById("copyBtn").onclick = () => {
|
||||||
|
navigator.clipboard.writeText(output.textContent);
|
||||||
|
alert("Copied!");
|
||||||
|
};
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.removeListener(listener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user