Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ninmonkey/b59e33cec6765a2c782edaf5c4807b17 to your computer and use it in GitHub Desktop.

Select an option

Save ninmonkey/b59e33cec6765a2c782edaf5c4807b17 to your computer and use it in GitHub Desktop.
Web Scraping Example - Using CSS Selector Queries.js
#requires -Modules PSParseHTML
<#
.link
javascript answer: https://gist.github.com/ninmonkey/b59e33cec6765a2c782edaf5c4807b17
#>
Import-Module PSParseHTML
$url = 'https://tavex.pl/zloto/zlote-sztabki/page/1?filter%5Bweight%5D%5B0%5D=1&meta%5B0%5D=tax-gold%3Azlote-sztabki&sorting=recommended'
$html ??= Invoke-WebRequest -url $Url -UseBasicParsing
$doc ??= ConvertFrom-Html -Content $html -Engine AngleSharp # AngleSharp uses CSS Selector queries :)
$doc | ft -auto
( $parents = $doc.QuerySelectorAll('.product.product--gold') ) |Ft -auto
'Found {0} parents' -f $parents.count | Write-Host -fore blue
$summary = @(
foreach( $elem in $parents ) {
$title = $elem.QuerySelectorAll('.product__title-inner')[0].TextContent.Trim()
$labels = $elem.QuerySelectorAll( '.product__price-label' )
$price = $elem.QuerySelectorAll( '.product__price-value' )
foreach( $i in 0..($labels.count - 1 )) {
[pscustomobject]@{
Product = $title
Label = $labels[ $i ].TextContent.Trim()
Price = $price[ $i ].TextContent.Trim()
}
}
}
)
$summary | ft -auto
$summary | ConvertTo-Json
| Jq -C # if you have JQ, it adds syntax highlighting
/**
* @summary scraping objects from this url: <https://tavex.pl/zloto/?filter%5Bweight%5D%5B0%5D=1&meta%5B0%5D=%3A&sorting=recommended>
*/
str1 = `.product.product--gold` // grab the root product element
str2 = `.product.product--gold .product__price` // grab the root of the prices element
all_products = document.querySelectorAll( str1 )
all_prices = document.querySelectorAll( str2 ) // note this query loses the connection to the parent so I do it differently below.
all_products.forEach( (elem) => { elem.style.border = `4px dashed yellow` } )
all_prices.forEach( (elem) => { elem.style.border = `4px dashed orange` } )
// before looping, lets test we can grab nested prices
grab = grabPrices( all_products[1] )
console.table( grab, ['label', 'price'] )
function grabPrices( elem ) {
// once you have a parent product element, grab only prices that are children
const label = elem.querySelectorAll('.product__price-label')
const price = elem.querySelectorAll('.product__price-value')
const merged = Array.from(label).map((labelElem, index) => ({
label: labelElem.innerText,
price: price[index].innerText
}))
return merged
}
function printJson( target ) {
// pretty-print as json
console.log( JSON.stringify( target, null, 4 ) )
}
/*
for each product element, drill into its children to find prices
save that list with the product's title.
*/
summary = Array
.from(all_products)
.map( (root) => {
const title = root.querySelector(`.product__title-inner`).innerText
const prices = grabPrices( root )
return {
title,
prices
}
})
// preview the first row of data. if this is for a tabular datasource
// you'll probably want to expand the prices list, so you have a flat table at the end
printJson( summary[0] )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment