The goal is to launch the html page, enter a url from booking.com, click the button, and have the scraped hotel name, rating, etc returned in the console.
So far, it does not return anything when clicking the button.
It works when the URL is hard-coded, but It says "main is declared but value is never read" in this form. Am i calling the function incorrectly? I'm still new to puppeteer, perhaps I'm overlooking something?
Here is app.js
function main()
{
var Url = document.getElementById('inputUrl').value
const puppeteer = require('puppeteer');
let bookingUrl = Url;
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto(bookingUrl);
// get hotel details
let hotelData = await page.evaluate(() => {
let hotels = [];
// get the hotel elements
let hotelsElms = document.querySelectorAll('div.sr_property_block[data-hotelid]');
// get the hotel data
hotelsElms.forEach((hotelelement) => {
let hotelJson = {};
try {
hotelJson.name = hotelelement.querySelector('span.sr-hotel__name').innerText;
hotelJson.reviews = hotelelement.querySelector('div.bui-review-score__text').innerText;
hotelJson.rating = hotelelement.querySelector('div.bui-review-score__badge').innerText;
if(hotelelement.querySelector('div.bui-price-display__value.prco-inline-block-maker-helper'))
{
hotelJson.price = hotelelement.querySelector('div.bui-price-display__value.prco-inline-block-maker-helper').innerText;
}
hotelJson.imgUrl = hotelelement.querySelector('img.hotel_image').attributes.src.textContent;
}
catch (exception){
}
hotels.push(hotelJson);
});
return hotels;
});
console.dir(hotelData);
})();
}
Here is index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="app.js" type="text/javascript"></script>
<title></title>
<meta name="description" content="">
<link rel="stylesheet" href="">
</head>
<input id = "inputUrl" type="text" placeholder = "type url here"/>
<button id = "button" button onclick="main();"> click</button>
<body>
<script src="" async defer></script>
</body>
</html>
You could add this before the evaluate:
await page.waitForSelector('div.sr_property_block[data-hotelid]');
Related
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TV Show Search</title>
<script src="https://cdn.jsdelivr.net/npm/axios#1.1.2/dist/axios.min.js"></script>
</head>
<body>
<h1>TV Show Search</h1>
<form id="searchForm">
<input type="text" placeholder="TV Show title" name="query">
<button>Search</button>
</form>
<script src="app.js"></script>
</body>
</html>
The result of displayed image in the browser
The below code is searching the picture element data in api and it will display the picture after searching it, My goal is while the first searched picture displayed and when i'm trying to search for the different element the previous displayed picture should be deleted. Right now when i search it prints from where the last picture displayed in the browser.
const form = document.querySelector('#searchForm');
const input = document.querySelector('.name');
form.addEventListener('submit', async function(e) {
e.preventDefault();
const searchTerm = form.elements.query.value;
const config = {params: {q: searchTerm}}
const res = await axios.get(`https://api.tvmaze.com/search/shows`, config)
form.elements.query.value = ''
// console.log(res.data[0].show.image.medium);
// form.elements.query.value = '';
// const img = document.createElement('IMG');
// img.src = res.data[0].show.image.medium;
// document.body.append(img)
makeImages(res.data)
})
const makeImages = (shows) => {
for(let result of shows){
if(result.show.image) {
const img = document.createElement('IMG');
img.src = result.show.image.medium;
document.body.append(img);
}
}
}
You should add a new container for images.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TV Show Search</title>
<script src="https://cdn.jsdelivr.net/npm/axios#1.1.2/dist/axios.min.js"></script>
</head>
<body>
<h1>TV Show Search</h1>
<form id="searchForm">
<input type="text" placeholder="TV Show title" name="query">
<button>Search</button>
</form>
<div id="results-container"></div><!-- new container -->
<script src="app.js"></script>
</body>
</html>
Then the first thing you should do in makeImages is clear all the children inside the container.
const form = document.querySelector('#searchForm');
const input = document.querySelector('.name');
form.addEventListener('submit', async function(e) {
e.preventDefault();
const searchTerm = form.elements.query.value;
const config = {params: {q: searchTerm}}
const res = await axios.get(`https://api.tvmaze.com/search/shows`, config)
form.elements.query.value = ''
// console.log(res.data[0].show.image.medium);
// form.elements.query.value = '';
// const img = document.createElement('IMG');
// img.src = res.data[0].show.image.medium;
// document.body.append(img)
makeImages(res.data)
})
const makeImages = (shows) => {
let container = document.querySelector('#results-container');
container.empty(); // remove all previous images
for(let result of shows){
if(result.show.image) {
const img = document.createElement('IMG');
img.src = result.show.image.medium;
container.append(img); // add images to the container instead of adding them directly to the body.
}
}
}
I'm trying to display all elements of an array, by iterating through the arrray, but after I chose the file (from the input), the element in page changes to : "unidentified". Why?
function getElement() {
console.log('sfgsdf')
document.getElementById('files').onchange = function() {
console.log('sfgsdf')
let file = this.files[0];
let reader = new FileReader();
reader.readAsText(file);
reader.onload = function() {
variableIs = this.result
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
function display(asd) {
const usingSplit = asd.split(' ')
lengthOf = usingSplit.length
for (var i = 0;i < lengthOf;i++) {
sleep(1000).then(() => {
document.getElementById('test').innerHTML = usingSplit[i];
});
}
}
display(variableIs);
}
}
}
getElement()
The HTML code is just this simple one :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1 id="test">TEST</h1>
<script src="test4.js"></script>
</body>
</html>
The problem is the var inside the for loop.
You should use let instead due to the way both work.
Read this post to understand their difference:
What is the difference between "let" and "var"?
The way you're using the sleep function is not gonna work since they will execute at the same time.
You can solve this by using async await.
function delay(ms = 0) {
return new Promise(resolve => setTimeout(resolve, ms))
}
const inputFile = document.getElementById('files')
const test = document.getElementById('test')
function init() {
inputFile.onchange = async function() {
const file = this.files[0];
const content = await file.text()
const splitText = content.split(' ')
for (let i = 0; i < splitText.length; i++) {
test.innerHTML = splitText[i]
// Here we are actually waiting in the for loop since this is an async function
await delay(1000)
}
}
}
init()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1 id="test">TEST</h1>
<input id="files" type="file">
</body>
</html>
I am trying to get the return results (title, content, poet) to show up on the HTML. Right now, only the content is changing dynamically whenever I refresh the page. I'm not sure what I am doing wrong in .then() - can you put multiple document.getElementId in there, or is there another way to structure it?
Note: I commented the other document.getElementId and document.getElementsByTagName because they just ended up showing the entire content 2 times
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel = "stylesheet" href = "style.css">
<title>Fetch a poem</title>
</head>
<body>
<h1 class = "title">Title</h1>
<h3 id = "content">Fetch a Poem</h3>
<p id = "poet">Poet</p>
<script>
console.log('about to fetch a poem');
catchPoem()
.then(poem => {
// document.getElementsByClassName('title').innerText = poem;
document.getElementById('content').innerText = poem;
// document.getElementById('poet').innerText = poem;
console.log('content is showing');
})
.catch(error => {
console.log('error!');
console.error(error);
});
async function catchPoem() {
const response = await fetch('https://www.poemist.com/api/v1/randompoems');
let json = await response.json();
let title = json[0].title
let content = json[0].content
let poet = json[0].poet.name
console.log(title)
console.log(content)
console.log(poet)
return [title, content, poet]
}
</script>
</body>
</html>
You need to set all three in the .then block
document.querySelector( '.title' ).textContent = title;
document.getElementById( 'content' ).textContent = content;
document.getElementById( 'poet' ).textContent = poet;
I've used textContent here, You can use innerText
console.log('about to fetch a poem');
catchPoem()
.then(([title, content, poet]) => {
// document.getElementsByClassName('title').innerText = poem;
document.querySelector('.title').textContent = title;
document.getElementById('content').textContent = content;
document.getElementById('poet').textContent = poet;
// document.getElementById('poet').innerText = poem;
console.log('content is showing');
})
.catch(error => {
console.log('error!');
console.error(error);
});
async function catchPoem() {
const response = await fetch('https://www.poemist.com/api/v1/randompoems');
let json = await response.json();
let title = json[0].title
let content = json[0].content
let poet = json[0].poet.name
return [title, content, poet]
}
h1, p{
text-align: center;
}
h1, h3, p{
padding: .5rem 1rem;
border-radius: 4px;
}
.title{
background-color: cadetblue;
}
#content{
background-color: chocolate;
}
#poet{
background-color: yellow;
}
<h1 class="title">Title</h1>
<h3 id="content">Fetch a Poem</h3>
<p id="poet">Poet</p>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel = "stylesheet" href = "style.css">
<title>Fetch a poem</title>
</head>
<body>
<h1 id = "title">Title</h1>
<h3 id = "content">Fetch a Poem</h3>
<p id = "poet">Poet</p>
<script>
console.log('about to fetch a poem');
catchPoem()
.then(poem => {
document.getElementById('title').innerText = poem[0];
document.getElementById('content').innerText = poem[1];
document.getElementById('poet').innerText = poem[2];
console.log('content is showing');
})
.catch(error => {
console.log('error!');
console.error(error);
});
async function catchPoem() {
const response = await fetch('https://www.poemist.com/api/v1/randompoems');
let json = await response.json();
let title = json[0].title
let content = json[0].content
let poet = json[0].poet.name
console.log(title)
console.log(content)
console.log(poet)
return [title, content, poet]
}
</script>
</body>
</html>
Another Way Of Generalization
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="style.css" />
<title>Fetch a poem</title>
</head>
<body>
<div id="content">
<p id="loader">Loading Poems ....</p>
</div>
<script>
console.log("about to fetch a poem");
catchPoem()
.then((poems) => {
let div = document.getElementById("content");
div.removeChild(document.getElementById("loader"));
for (let poem of poems) {
let title = document.createElement("h1");
title.innerHTML = poem.title || "No Title";
div.appendChild(title);
let poemTag = document.createElement("h3");
poemTag.innerHTML = poem.content || "No Poem";
div.appendChild(poemTag);
let poet = document.createElement("p");
poet.innerHTML = poem.poet.name || "No Poet";
div.appendChild(poet);
}
})
.catch((error) => {
console.log("error!" + error);
});
async function catchPoem() {
const response = await fetch("https://www.poemist.com/api/v1/randompoems");
let json = await response.json();
return json;
}
</script>
</body>
</html>
please am trying to integrate sending any trc20 token using tronlink by clicking a button on my website. I was able to send TRX using the JavaScript code below but I want to be able to send trc-20 like USDT, any help will be highly appreciated. Thanks
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
<input type="text" name="numb" id="numb">
<button onclick="sendtron()">Can you get tronweb from tronlink?</button>
</div>
<script>
function sendtron(){
var obj = setInterval(async ()=>{
if (window.tronWeb && window.tronWeb.defaultAddress.base58) {
clearInterval(obj)
var tronweb = window.tronWeb
var amount = document.querySelector('#numb').value;
var tokens = amount * 1000000
var tx = await tronweb.trx.sendTransaction("TWs2Z7dLMcPnXi9pnWqCUPzAnqUv6T54dy", tokens)
var signedTx = await tronweb.trx.sign(tx)
var broastTx = await tronweb.trx.sendRawTransaction(signedTx)
console.log(broastTx);
}
});
}
</script>
</body>
</html>
TRC20 are actually smart contracts. tronscan USDT link To transfer TRC20 from your address to another address, you will be calling TRC20's transfer function, below is a snippet of Tron USDT's code.
function transfer(address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[msg.sender]);
// SafeMath.sub will throw if there is not enough balance.
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
return true;
}
TronWeb TRC20 Contract Interaction documentation. You can use tronWeb's triggerSmartContract function to create a raw transaction, sign and broadcast.
create raw transaction
var senderAddress = tronweb.defaultAddress.base58;
var receiverAddress = "TV3nb5HYFe2xBEmyb3ETe93UGkjAhWyzrs";
var amount = 100;
var parameter = [{type:'address',value:receiverAddress},{type:'uint256',value:amount}]
var options = {
feeLimit:100000000
}
const transactionObject = await tronWeb.transactionBuilder.triggerSmartContract(
tronweb.address.toHex(contractAddress),
"transfer(address,uint256)",
options,
parameter,
tronweb.address.toHex(senderAddress)
);
Note: address are all in base58 format, we need to convert it to hex format using tronweb.address.toHex(address) at transactionObject. The parameter variable is where we set the receiver address and amount.
Sign
var signedTransaction = await tronWeb.trx.sign(transactionObject.transaction);
Broadcast
var broadcastTransaction = await tronWeb.trx.sendRawTransaction(signedTransaction);
console.log(broadcastTransaction);
When I inspect the code in the browser this error appears spread.js.25 and I can not find this problem.
I checked the exercise solution, it's the same as my solution ... I don't know much about axios ...
<!DOCTYPE html>
<html lang="en">
<head>
<title>ExercĂcio 02</title>
</head>
<body>
<input type="text" name="user">
<button onclick="listRepositories()">Adicionar</button>
<ul></ul>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var listElement = document.querySelector('ul');
var inputElement = document.querySelector('input');
function renderRepositories(repositories) {
for (repo of repositories) {
const textElement = document.createTextNode(repo.name);
const liElement = document.createElement('li');
liElement.appendChild(textElement);
listElement.appendChild(liElement);
}
}
function listRepositories() {
var user = inputElement.value;
if (!user) return;
axios.get('https://api.github.com/users/' + user + '/repos')
.then(function (response) {
renderRepositories(response.data);
})
}
</script>
</body>
</html>
this image is exactly the problem