I have this code on a website
<div id="productPriceJSON_18678511" style="display:none;">
[{
"isXPromoProd":"true",
"mfPartNumber":"961576-BLACK",
"productGroupId":"18678008",
"productId" : "18678511",
"listPrice" :"$85.00",
"offerPrice" :"$85.00",
"discountPrice" :"$42.50",
"lowestPriceAmount" :"$42.50",
"highestPriceAmount" :"$42.50",
"colorCount" : "0",
"isPriceVary" :"false"
}]
</div>
There are different DIVs with different SKU variable productPriceJSON_18678522, productPriceJSON_18678533,productPriceJSON_18678544 and so on.
I want to do 2 things:
Import all the DIVs that contain productPriceJSON_, I tried using
//div[#id=[contains(.,"skuPriceJSON_")]]
But no luck
How can I get the discount price from this DIV matching $42.50?
Really appreciate the help here.
Cheers,
B.
Related
I've found the lowest class: <span class="pill css-1a10nyx e1pqc3131"> of multiple elements of a website but now I want to find the related/linked upper-class so for example the highest <div class="css-1v73czv eh8fd9011" xpath="1">. I've got the soup but can't figure out a way to get from the 'lowest' class to the 'highest' class, any idea?
<div class="css-1v73czv eh8fd9011" xpath="1">
<div class="css-19qortz eh8fd9010">
<header class="css-1idy7oy eh8fd909">
<div class="css-1rkuvma eh8fd908">
<footer class="css-f9q2sp eh8fd907">
<span class="pill css-1a10nyx e1pqc3131">
End result would be:
INPUT- Search on on all elements of a page with class <span class="pill css-1a10nyx e1pqc3131">(lowest)
OUTPUT - Get all related titles or headers of said class.
I've tried it with if-statements but that doesn't work consistently. Something with an if class = (searchable class) then get (desired higher class) should work.
I can add any more details if needed please let me know, thanks in advance!
EDIT: Picture per clarification where the title(highest class) = "Wooferland Festival 2022" and the number(lowest class) = 253
As mentioned, question needs some more information, to give a concret answer.
Assuming you like to scrape the information in the picture based on your example HTML you select your pill and use .find_previous() to locate your elements:
for e in soup.select('span.pill'):
print(e.find_previous('header').text)
print(e.find_previous('div').text)
print(e.text)
Assuming there is a cotainer tag in HTML structure like <a> or other you would select this based on the condition, that it contains a <span> wit class pill:
for e in soup.select('a:has(span.pill)'):
print(e.header.text)
print(e.header.next.text)
print(e.footer.span.text)
Note: Instead of using css classes, that can be highly dynamic, try use more static attributes or the HTML structure.
Example
See both options, for first one the <a> do not matter.
from bs4 import BeautifulSoup
html='''
<a>
<div class="css-1v73czv eh8fd9011" xpath="1">
<div class="css-19qortz eh8fd9010">
<header class="css-1idy7oy eh8fd909">some date information</header>
<div class="css-1rkuvma eh8fd908">some title</div>
<footer class="css-f9q2sp eh8fd907">
<span class="pill css-1a10nyx e1pqc3131">some number</span>
<footer>
</div>
</div>
</a>
'''
soup = BeautifulSoup(html)
for e in soup.select('span.pill'):
print(e.find_previous('header').text)
print(e.find_previous('div').text)
print(e.text)
print('---------')
for e in soup.select('a:has(span.pill)'):
print(e.header.text)
print(e.header.next.text)
print(e.footer.span.text)
Output
some date information
some title
some number
---------
some date information
some date information
some number
So, I am trying to create a table here which has all the keys on left column named "Specs" and all the values on right column named "Value" from the json data that I have. And, I need to display that on my html page as a table. I am doing this in python and flask and I am having a hard time figuring out a jinja syntax for that.
So, I have route "/Specs" and a function called specs as shown below and whenever a user clicks a button in my main.html page this specs function gets called which basically fetches json data (host facts basically) and I know how to send this json data to my html page as shown below:
#app.route('/Specs', methods=['GET', 'POST'])
def Specs():
ID = request.form["foremanId1"]
print(ID)
response10 = requests.get('https://test.com/api/hosts/{v1}/facts'.format(v1=ID), auth=('abc', 'password'), verify=True)
if response10.status_code == 200:
myDictForHostsFacts = json.loads(response10.content.decode('utf-8'))
return render_template('provision.html', data=myDictForHostsFacts)
As you can see, I am sending this json data as data to my provision.html page which is a very simple html page that only needs to display this data as key value pair. Here is my html code.
<!DOCTYPE html>
<html>
<head>
<h1> Specifications related to this system:</h1>
</head>
<body>
<table class="table table-dark">
<thead class="thead thead-dark">
<tr>
<!-- Your Columns HERE -->
<th class="header text-left" scope="col">Specs</th>
<th class="header text-left" scope="col">Value</th>
</tr>
</thead>
<tbody id="temp-table">
{% for entry in data.results %}
<tr>
<td class="text-left">{{entry}}</td>
<td class="text-left">{{data.results[entry]}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
Here is my json data:
{"total": 366, "subtotal": 1, "page": 1, "per_page": 320, "search": " host = 529", "sort": {"by": null, "order": null}, "results": {"mac7287327223": {"memory::system": null, "dmi::board": null, "disks::sdb::size_bytes": "0", "nmprimary_ipv4_dns-priority": "0", "nmprimary_ipv6_dns-priority": "0", "nmprimary_802-3-ethernet_speed": "0", "nmprimary_ipv4_route-table": "0", "nmprimary_ipv6_route-table": "0", "dmi::bios::release_date": "03/08/2022", "bios_release_date": "03/08/2022", "disks::sdb::size": "0 bytes", "partitions::/dev/loop2::size": "1.56 GiB", "partitions::/dev/mapper/live-rw::size": "1.56 GiB", "partitions::/dev/mapper/live-base::size": "1.56 GiB", "partitions::/dev/loop4::size": "1.56 GiB", "processorcount": "16", "processors::count": "16", "nmprimary_dhcp4_option_expiry": "1661435487", "partitions::/dev/loop2::size_bytes": "1677721600", "partitions::/dev/mapper/live-rw::size_bytes": "1677721600", "partitions::/dev/loop4::size_bytes": "1677721600"}}}
The problem is whenever I run it, it is only displaying mac7287327223 on the left column and no value on the right column. I only want to display all the keys that are inside mac7287327223{..} on left column and their respective values on the right column so, my table would look like this:
| Specs | value |
| memory::system | null |
| dmi::board | null |
| disks::sdb::size | 0 bytes |
| processorcount | 16 |
I was getting errors when I tried to format this table in a proper manner so, I have it like this sorry for that, but you get an idea of what I am trying to accomplish here.
So, my question is how do I get keys and their respective values that are inside mac7287327223 {.....} and leave everything out. I just need to display those in the table under specs and value. Having problem because these are keys within keys.
Any help will be highly appreciated and thank you for your time!
I am making a website of my shop items, where I need to daily update the items which includes item_name, brand_name, price, item_no., etc. Writing html codes daily is becoming very hard work for me. So, I want to make changes about the items in a CSV file, and import the data into my website. How to do that, Please help me. Thank you in advance. Here is some sample codes:
read_data.html
<html>
<head><title>Reading values from csv file</title></head>
<style type="text/css">
div{
width: 300px;
}
img{
height: 200px;
}
</style>
<body>
<div>
<img src="#" alt="item 1"><br>
Item Name:<!--CSV file data--><br>
Item Number:<!--CSV file data--><br>
Brand Name:<!--CSV file data-->
</div>
<div>
<img src="#" alt="item 2"><br>
Item Name:<!--CSV file data--><br>
Item Number:<!--CSV file data--><br>
Brand Name:<!--CSV file data-->
</div>
</body>
</html>
data.csv
Item Name,Item no.,Brand
T-shirt,555,Hoffmen
Pants,556,Reliance
Edit: this is assuming you have a way to store the data (e.g. a database). It sounds like you would benefit from a CMS (e.g. Wordpress). Anyway, this answer addresses the question of how to get the CSV data:
You can use Papa parse. It would look something like this:
// from file upload field
var file = event.target.inputCSV.value;
var data = Papa.parse(file, {header: true, skipEmptyLines: true, delimiter: ','});
return data;
// outputs something like [{Item_Name: "T-shirt", Item_no: 555, Brand: "Hoffman"}, {Item_Name: "Pants", Item_no: 556, Brand: "Reliance"}]
As suggested by Saptarshi, you'll probably need a database for this, where you can possibly import your CSV. This will help your handling and automize it. The solution might be based on a php/mySQL basis, for example. I'd do some research on the specialties and power of these languages first.
Below is my JSON file:
[
{
"Name":"Peter England Shirt",
"Prodimage":["./images/zoom/zoom1hi.jpg","./images/zoom/zoom2hi.jpg","./images/zoom/zoom3hi.jpg"],
"actualPrice":"90",
"discountedPrice":"70",
"desc":"Cotton",
"Prodcolor":["#f1f40e","#adadad","#4EC67F"],
"quantity":[1,3,4,5,60],
"size":["XL","L","M","S"],
"detail":"Take it away",
"sizeChart":["16 waist","Measurements taken from size 30","Model wears size 31. Model is 6'2"],
"shipping":[
{
"type":"Standard",
"days":"5-6 days",
"cost":"200"
},{
"type":"Next day",
"days":"1 days",
"cost":"500"
}
],
"sellerList":[
{
"sellerName":"ABC",
"price":"566",
"deliveryDay":"4-5 working days"
},{
"sellerName":"SEDF",
"price":"300",
"deliveryDay":"4-5 working days"
},{
"sellerName":"QWER",
"price":"555",
"deliveryDay":"2-5 working days"
}
]
}
]
The JS file is as below:
var pJson="./json/product.json";
$http.get(pJson).success(function(response){
$scope.product=response;});
Now, if I want to access "Name" attribute I can call {{product[0].Name}}.
But I am not able to access Prodimage attribute using ng-repeat. I am trying like this:
<div ng-repeat="image in product.Prodimage">
{{image[0]}}
</div>
is this wrong?>
Yes this is wrong ,, note that you have the product object as array ,, so if you want the first object you should do this
<div ng-repeat="image in product[0].Prodimage">
{{image[0]}}
</div>
or if you want to iterate over all the products ,, you need to make a nested ng-repeat
<div ng-repeat="p in product">
<div ng-repeat="image in p.Prodimage">
{{image[0]}}
</div>
</div>
You could loop over it, becasue the outside is technically an array, and use $first for you example of wanting to only grab the first image. You could also use $index but running it through a function that checks the $index.
Fiddle here http://jsfiddle.net/HB7LU/15324/
I just re worked it to loop twice like so
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
<div ng-show="$first">
{{image}}
</div>
</div>
</div>
then put a div inside the inner repeat that will only show if it's the first item. Again you could change that logic to show by index, or whatever you want. So if you know the index you could change that same logic to this -
see fiddle - http://jsfiddle.net/HB7LU/15332/
<div ng-show="checkIndex($index)"> << or whatever index you want
{{image}}
</div>
and in the controller
$scope.checkIndex = function(item){
if(item === 0){
return true;
}else{
return false;
}
}
You just pass the index of the current item in the repeat and check it. I would recommend this logic over the Prodimage[0] logic so you are not hardcoding it into the html, so if you have to change the desired index, you change it in the controller, not template. The checkIndex is a quick example, you could change that to do whatever you want.
$scope.product[n].Prodimage is an array. So, you need to loop through your product array first, and then loop through the Prodimage array of each product:
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
{{ image }}
</div>
</div>
Of course, you could also just access the nth image using something like:
<div ng-repeat="prod in product">
{{ prod.Prodimage[0] }}
</div>
Can you change your json to
"Prodimage":[
{ "loc": "./images/zoom/zoom1hi.jpg"},
{ "loc": "./images/zoom/zoom2hi.jpg"},
{ "loc": "./images/zoom/zoom3hi.jpg"}],
then your loop should work
<div ng-repeat="image in product.Prodimage">
{{image.loc}}
</div>
Hi I am new to angular I have a requirment as follows.
app.js
$scope.fields = {
"fields": {
"LastName1": "ABC",
"FirstName1": "XYZ",
"LastName2": "123",
"FirstName2": "345",
"LastName3": "PQR",
"FirstName3": "ASD",
}
};
In my html I need to loop over this and display in
index.html
<tr ng-repeat="key in fields">
this doesn't seem to work. Please help.
I want my output as
LastName1 ABC
FirstName1 XYZ
and so on.
Also If user makes any changes to this, I want to be able to push the changes back to fields Json. Please help.
You can use the (key, value) in object syntax.
In your case :
<div ng-repeat="(key1, value1) in fields">
<li ng-repeat="(key2, value2) in value1">{{key2}} : {{value2}}</li>
</div>.
But :
You need to be aware that the JavaScript specification does not define
the order of keys returned for an object. (To mitigate this in Angular
1.3 the ngRepeat directive used to sort the keys alphabetically.)
Version 1.4 removed the alphabetic sorting. We now rely on the order
returned by the browser when running for key in myObj. It seems that
browsers generally follow the strategy of providing keys in the order
in which they were defined, although there are exceptions when keys
are deleted and reinstated. See
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues
If this is not desired, the recommended workaround is to convert your
object into an array that is sorted into the order that you prefer
before providing it to ngRepeat. You could do this with a filter such
as toArrayFilter or implement a $watch on the object yourself.
More details : https://docs.angularjs.org/api/ng/directive/ngRepeat
Edit : What if you want to change the object now ?
You can't do :
<div ng-repeat="(key1, value1) in fields">
<h3>{{key1}}</h2>
<li ng-repeat="(key2, value2) in value1">
<input ng-model="value2" /><br />
{{key2}} : {{value2}}
</li>
</div>
Why ? Because ng-model will change value2 in the current scope, and not in your object fields as you don't use dot notation.
For each item/iteration, ng-repeat creates a new scope, which
prototypically inherits from the parent scope, but it also assigns the
item's value to a new property on the new child scope.
More details : https://github.com/angular/angular.js/wiki/Understanding-Scopes
But you can do :
<div ng-repeat="(key1, value1) in fields">
<h3>{{key1}}</h2>
<li ng-repeat="(key2, value2) in value1">
<input ng-model="fields[key1][key2]" /><br />
{{key2}} : {{value2}}
</li>
</div>
Take a look !!!
Try change to:
<tr ng-repeat="(key, value) in fields.fields">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
Here is a working plunker where you can update the model: http://jsfiddle.net/ttgfybk0/1/
Repeat data is in object format like
{
"LastName1": "ABC",
"FirstName1": "XYZ",
"LastName2": "123",
"FirstName2": "345",
"LastName3": "PQR",
"FirstName3": "ASD",
}
use the ng-repeat="(key, value) in expression"
<tr ng-repeat="(key, value) in fields.fields">
<td>{{key}} {{value}}</td>
</tr>
working example ishttp://plnkr.co/edit/Y5lPH1?p=preview