Public
Edited
Feb 11
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
//diskPrices = await getDiskPrices(inputsDiskPrices)
Insert cell
//viewof table = Inputs.table(diskPrices)
Insert cell
viewof inputProxy = Inputs.form({
cors: Inputs.select(corsList, {label: 'CORS proxy'}),
})
Insert cell
// general function to scrape DiskPrices.com
// inputs parameters, forms URL, returns an array of objects containing each result
getDiskPrices = async (inputs) => {
// check for CORS
const url = inputProxy.cors + formDiskPriceURL(inputs)
try {
// get data
const response = await fetch(url, fetchConfig);
if (!response.ok) throw new Error(`HTTP error: ${response.status}`);
// parse as HTML
const text = await response.text();
const parser = new DOMParser();
const doc = parser.parseFromString(text, 'text/html');

// save each result into an array of objects
const disks = [...doc.querySelectorAll('tr.disk')].map(row => ({
pricePerGB: row.querySelector('.price-per-gb')?.textContent.trim() || null,
pricePerTB: row.querySelector('.price-per-tb')?.textContent.trim() || null,
totalPrice: row.children[2]?.textContent.trim() || null,
capacity: row.children[3]?.textContent.trim() || null,
type: row.children[5]?.textContent.trim() || null,
interface: row.children[6]?.textContent.trim() || null,
condition: row.children[7]?.textContent.trim() || null,
name: row.querySelector('.name a')?.textContent.trim() || null,
link: row.querySelector('.name a')?.href || null
}));
return disks;
} catch (error) {
console.error('Error:', error);
return [];
}
}
Insert cell
Insert cell
corsList = ["",
//"https://cors-anywhere.herokuapp.com/" // doesn't work anymore
]
Insert cell
fetchConfig = new Object({
'origin': 'https://observablehq.com/d/5cc09d57ee6ecad7'
})
Insert cell
/*
<table id="diskprices">
<thead>
<tr id="diskprices-head">
<th class="price-per-gb hidden">Price&nbsp;per&nbsp;GB</th>
<th class="price-per-tb">Price&nbsp;per&nbsp;TB</th>
<th>Price</th>
<th>Capacity</th>
<th>Warranty</th>
<th>Form&nbsp;Factor</th>
<th>Technology</th>
<th>Condition</th>
<th>Affiliate Link</th>
</tr>
</thead>
<tbody id="diskprices-body" lang="en">
<tr class="disk" data-product-type="internal_sas" data-condition="used" data-capacity="3000.0">
<td class="price-per-gb hidden">$0.003</td>
<td class="price-per-tb">$3.000</td>
<td>$9</td>
<td>3 TB</td>
<td></td>
<td>Internal</td>
<td>SAS</td>
<td>Used</td>
<td class="name"><a href="https://www.amazon.com/dp/B00CK00QL6?tag=synack-20&linkCode=osi&th=1&psc=1">Seagate Constellation ES.2 ST33000650SS 3 TB 3.5"</a></td>
</tr>
*/
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more