I need to get list elements with web scraping. I can't reach elements one by one, I can get all elements in one string. How can I get list elements using SwiftSoup or any other option?
Here my function:
self.webView.evaluateJavaScript("document.getElementsByTagName('html')[0].innerHTML") { (value, error) in
if error != nil {
print("Err: \(error)")
}else{
//print(value!)
self.innerDetail = value as! String
do {
let html = self.innerDetail
let doc: Document = try SwiftSoup.parse(html)
// BURADA IMAGE URL LERINI ALIRIZ DETAY SAYFALARI ICIN...
let imageLink = try doc.getElementsByClass("img-container")
let src: Elements = try imageLink.select("img[src]")
let imageUrlStringArray: [String?] = src.array().map { try? $0.attr("src").description }
print(imageUrlStringArray) // BUNDA BUTUN DETAY IMAGE URL LERI SAKLANIR..
// BURADA ARABANIN MARKASI MODELI YILI KM VE YAKIT OLARAK CEKILMESI GEREKMEKTEDIR..
// ONCE FIYATI TABIKI..
let priceMainClass = try doc.getElementsByClass("price")
print(try priceMainClass.text()) // BU FIYATTIR..
// BURDA COK FAZLA DATA GELIYOR VE LISTE SEKLINDELER..
let detailClass = try doc.getElementsByClass("classified-info-list").first()
print(try detailClass?.html())
print(try detailClass?.text())
let detailFeatures = try detailClass?.text()
//print(detailFeatures)
//self.detailFeaturesArr = detailFeatures?.components(separatedBy: " ") as! [String]
} catch {
print("err")}
}
In detailClass?.text() I can get data but it is one string. In detailClass?.html() have list which I want to get data from there.
Here list data detailClass?.html():
Optional("<li> <strong>Fiyat</strong> <span class=\"price\"> 77.500 TL<input id=\"priceHistoryFlag\" type=\"hidden\" value=\"\" autocomplete=\"off\"> \n <!-- ngIf: hasPriceHistory --> \n <!-- ngIf: hasPriceHistory --> </span> </li> \n<li> <strong> İlan Tarihi</strong> <span> 01 Ekim 2020</span> </li> \n<li> <strong>İlan No</strong> <span class=\"classifiedId\" id=\"classifiedId\">865620915</span> </li> \n<li> <strong>Marka</strong> <span>Volvo </span> </li> \n<li> <strong>Seri</strong> <span>S40 </span> </li> \n<li> <strong>Model</strong> <span>2.0 T </span> </li> \n<li> <strong>Yıl</strong> <span class=\"\"> 1999</span> </li> \n<li> <strong>Yakıt</strong> <span class=\"\"> Benzin & LPG</span> </li> \n<li> <strong>Vites</strong> <span class=\"\"> Otomatik</span> </li> \n<li> <strong>KM</strong> <span class=\"\"> 178.000</span> </li> \n<li> <strong>Kasa Tipi</strong> <span class=\"\"> Sedan</span> </li> \n<li> <strong>Motor Gücü</strong> <span class=\"\"> 160 hp</span> </li> \n<li> <strong>Motor Hacmi</strong> <span class=\"\"> 1948 cc</span> </li> \n<li> <strong>Çekiş</strong> <span class=\"\"> Önden Çekiş</span> </li> \n<li> <strong>Renk</strong> <span class=\"\"> Gümüş Gri</span> </li> \n<li> <strong>Garanti</strong> <span class=\"\"> Hayır</span> </li> \n<li> <strong>Plaka / Uyruk</strong> <span class=\"\"> Türkiye (TR) Plakalı</span> </li> \n<li> <strong>Kimden</strong> <span class=\"fromOwner\"> Sahibinden</span> </li> \n<li> <strong>Görüntülü Arama İle Görülebilir</strong> <span class=\"\"> Evet</span> </li> \n<li> <strong>Takas</strong> <span> Hayır </span> </li> \n<li> <strong>Durumu</strong> <span> İkinci El </span> </li> \n<li class=\"hiddenAttributes\"> <input type=\"hidden\" autocomplete=\"off\" class=\"classifiedAttr\" id=\"attrClassifiedId\" value=\"865620915\"> <input type=\"hidden\" autocomplete=\"off\" class=\"classifiedAttr\" id=\"attrIsShipping\" value=\"false\"> </li>")
Sorry about my english. I hope it will be understandable.
I solve problem added code below. I found answer at python question here: How to get a list of the <li> elements in an <ul> with Selenium using Python?
Here my code:
// BURDA COK FAZLA DATA GELIYOR VE LISTE SEKLINDELER..
let detailClass = try doc.getElementsByClass("classified-info-list").first()
let listItems = try detailClass?.getElementsByTag("li")
for j in try listItems!{
let text = try j.text()
print(text)
}
Related
I'm currently trying to work on a basic JavaScript application.
I ultimately want to have a book that shows basic information on it's cover and with the click of a link, the book will show additional information.
I have two divs; #frontBook which will displays the front of the book which includes basic information about the current Book (i.e. Title, Author, Pages, Read or not) and #insideBook which will display additional info about the book(i.e. what page they're up to, publisher's name, etc.)
I want the #frontBook div to show and #insideBook to be hidden at first. Then once #additional-info link has been clicked, I want #frontBook to be hidden and #insideBook to be shown.
I've added my code below but it does not work. I'm really not sure where I'm going wrong. Please Help!
Thanks in advance.
P.S. I know that JQuery would be recommended for something like this but I just want to make sure I can grasp this concept with JavaScript first.
HTML:
<div id="frontBook">
<div id="book-outline">
<div id="book-content">
<ul id="basic-book-content">
<li><span class="basic-book-details" id="new-title">Title: </span></li>
<li><span class="basic-book-details" id="new-author">Author: </span></li>
<li><span class="basic-book-details" id="new-pages">Pages: </span></li>
<li><span class="basic-book-details" id="new-read">Read?:</span></li>
<li style="line-height: 80px; margin-right:-2px;">
<a href="#" id="additional-info" onclick="toggle_book();">Additional Info
<i style="color:white;" class="far fa-caret-square-right" ></i>
</a>
</li>
</ul>
</div>
<!-- closes #book-content-->
</div>
</div>
<div id="insideBook" style="display:none">
<div id="inside-book-outline">
<div id="inside-book-content">
<ul id="additional-book-content">
<li><span class="additional-book-details" id="new-editor"> Editor's Name: </span></li>
<li><span class="additional-book-details" id="new-publisher">Publisher's Name: </span></li>
<li><span class="additional-book-details" id="new-pub-comp">Publsiher Company's Name: </span></li>
<li><span class="additional-book-details" id="new-page-at">Page Up to:</span></li>
<li><span class="additional-book-details" id="new-line-at">Line Up to:</span></li>
<li><span class="additional-book-details" id="new-genre">Genre:</span></li>
<li><span class="additional-book-details" id="new-in-series">In Series?:</span></li>
<li style="line-height: 80px; margin-right:-2px;">
<a href="#" id="less-info" onclick="toggle_book();">
<i style="color:white;" class="far fa-caret-square-right"></i>Less Info
</a>
</li>
</ul>
</div>
<!-- closes #inside-book-content-->
</div>
</div>
JavaScript:
function toggle_book() {
var front = document.getElementById('frontBook');
var inside = document.getElementById('insideBook');
if (inside.style.display === 'block') {
inside.style.display = 'none';
front.style.display = 'block';
} else {
inside.style.display = 'block';
front.style.display = 'none';
}
}
Well you seemed to have missed two things.
1) You're if statement logic is backwards it should be:
function toggle_book() {
var front = document.getElementById('frontBook');
var inside = document.getElementById('insideBook');
if (inside.style.display === 'block') {
inside.style.display = 'none';
front.style.display = 'block';
} else {
inside.style.display = 'block';
front.style.display = 'none';
}
2) You don't have a onclick attribute for the <a> tag in the insideBook to toggle it back
Is it possible to change the html node structure ?
<span role="button" class="fancytree-expander"></span>
<span class="fancytree-title">
<div class="title">Direction Générale des Services</div>
<div class="agents">
<span class="agent">Directeur Général des Services<br>Jean-Marc Lucas<br><i class="fa fa-fw fa-phone"></i> : 02 96 13 59 59<br><i class="fa fa-fw fa-envelope"></i> contact#gp3a.bzh</span>
</div>
</span>
to
<span role="button" class="fancytree-expander"></span>
<span class="fancytree-title">
<div class="title">Direction Générale des Services</div>
</span>
<div class="agents">
<span class="agent">Directeur Général des Services<br>Jean-Marc Lucas<br><i class="fa fa-fw fa-phone"></i> : 02 96 13 59 59<br><i class="fa fa-fw fa-envelope"></i> contact#gp3a.bzh</span>
</div>
in other words, is it possible to add html node outsite of the span.fancytrre-title ?
Thx
Have a look at the Fancytree events, especially createNode and renderTitle.
Example:
function createNode(event, data) {
// add fake <input/> to the node
var $input = $("<input/>").val(data.node.title);
$("span.fancytree-title", data.node.li).before($input);
}
We have had a Tumblr page set up for a year with no issues until this past month.
We have a page redirect in our navigation bar. The redirect goes to our main website, WordBrewery.com. The link listed in the redirect is the main URL - http://www.wordbrewery.com.
Now it is redirecting to our site's 404 page and this is added to the end of the URL:
#_=_
I have tried using this script, but it has done nothing:
<script>
if (window.location.hash == "#_=_")
{
window.location.hash = "";
}
</script>
I have also tried replacing the main URL with a shortened Google version but this has not worked either.
Any help would be greatly appreciated.
EDIT:
The hard code that I am able to edit appears like this:
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
{block:IfShowAvatar}
<img src="{PortraitURL-128}" class="{AvatarShape}" alt="{Title}" />
{/block:IfShowAvatar}
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
{block:IfShowTitle}<li class="active">{Title}</li>{/block:IfShowTitle}
{block:IfShowArchiveLink}
<li>{lang:Archive}</li>
{/block:IfShowArchiveLink}
{block:IfShowRandomLink}
<li>{lang:Random}</li>
{/block:IfShowRandomLink}
{block:HasPages}
{block:Pages}<li>{Label}</li>{/block:Pages}
{/block:HasPages}
{block:AskEnabled}
<li>{AskLabel}</li>
{/block:AskEnabled}
{block:SubmissionsEnabled}
<li>{SubmitLabel}</li>
{/block:SubmissionsEnabled}
{block:IfTagMenuList}
<li class="dropdown">
<a href="#" id="tag-menu" data-toggle="dropdown" aria-expanded="true">
{text:Tag Menu Title} <span class="caret"></span>
</a>
<script>
var list = '{text:Tag Menu List}';
list = list.split(',');
var html = '<ul class="dropdown-menu" role="menu" aria-labelledby="tag-menu">';
for(var i=0; i<list.length; i++) {
html += '<li role="presentation"><a role="menuitem" tabindex="-1" href="/tagged/' + list[i] + '">#' + list[i] + '</a></li>';
}
html += '</ul>';
document.write(html);
</script>
</li>
{/block:IfTagMenuList}
{block:IfShowSearch}
<li><a class="icon-search search-overlay-show"></a></li>
{/block:IfShowSearch}
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
I am unsure of how to get rid of the string Tumblr adds to redirected URLs but alternatively you can hard code the link to avoid utilising Tumblr's redirect.
Beneath {block:HasPages} add <li>WordBrewery.com</li>
I want to create a form using an unordered list ul must have only two levels which I am not getting in this demo:
http://jsfiddle.net/rathoreahsan/9SCCn/
When I add a sub-list it adds one sub list of parent list (it is fine) but when I add another sub-list it adds a sub-list for newly added sub-list (that i don't want). I want when I add sub-list it only add 1 sub-list of a parent list instead of adding sub-list of newly added sub-lists.
Current Structure:
<ul>
<li><input type="text" />
<ul>
<li><input type="text" /></li> // New added sub list
<ul> //It should'nt be like this when added more
<li><input type="text" /></li>
</ul>
</li>
</ul>
</li>
</ul>
The structure should be like this:
<ul>
<li><input type="text" />
<ul>
<li><input type="text" /></li> // New added sub list
<li><input type="text" /></li> //It should be like this when added more
</ul>
</li>
</ul>
Edited
Finally got the solution See Workin Demo: http://jsfiddle.net/rathoreahsan/2hwLp/
JQUERY
$.fn.exists = function(){ return this.length>0; }
function dBtnClick(val){
if( $('#duties li#' + val + ' ul.sublists').exists() )
{
$('#duties li#' + val + ' ul.sublists').append('<li><input type="text" /></li>')
}
else if( !$('#duties li#' + val + ' ul.sublists').exists() )
{
$("#duties li#" + val).append('<ul class="sublists"><li><input type="text" /></li></ul>')
}
}
var dutiesListID = $('#duties li#0').attr('id');
var d_cur_no = parseInt(dutiesListID);
$('#dr').click(function(){
d_cur_no++;
$('#duties').append('<li id="' + d_cur_no + '"><input type="text" /> Add Sub List Item</li>');
});
HTML:
<h3>Duties and Responsibilities:</h3>
<ul id="duties">
<li id="0"><input type="text" /> Add Sub List Item</li>
</ul>
<span class="controls">
Add List Item
</span>
DEMO:
http://jsfiddle.net/rathoreahsan/2hwLp/
This might work:
change html part here:
<ul id="duties">
<li class="top-level"><input type="text" /></li>
</ul>
and js part here:
$('#dr-sub').click(function(){
$('.top-level').last().append('<ul><li><input type="text" /></li></ul>');
});
Try to change it like this:
$('#duties li').last().append('<li><input type="text" /></li>');
I have this piece of HTML
<div id="fileTreeInviati">
<ul class="php-file-tree">
<li class="pft-directory">
A006 - SOMETEXT (<span name="contaNew"></span>)
<img src="./moduli/home/images/info.png" title="Informazioni Azienda" class="imgInfo"/>
<ul style="display: none;">
<li class="pft-file ext-png">
cut.png
</li>
<li class="pft-file ext-dll">
Safari.dll
</li>
</ul>
</li>
<li class="pft-directory">
A012 - SOMETEXT (<span name="contaNew"></span>)
<img src="./moduli/home/images/info.png" title="Informazioni Azienda" class="imgInfo"/>
<ul style="display: none;">
<li class="pft-file ext-jpg">
04.jpg
</li>
<li class="pft-file ext-dll">
Safari.dll
</li>
</ul>
</li>
<li class="pft-directory">
A014 - SOMETEXT (<span name="contaNew"></span>)
<img src="./moduli/home/images/info.png" title="Informazioni Azienda" class="imgInfo"/>
<ul style="display: none;">
<li class="pft-file ext-txt">
acu.txt
</li>
<li class="pft-file ext-dll">
Safari.dll
</li>
</ul>
</li>
</ul>
I'm working on a js snippet that cycle through all "a" of the "li" and checks if it has the class "new" if yes increment a counter by one. This counter now has to be printed on the relative "li" "span" 3 level before.
So I have the number of the element with the "new" class.
The js snippet is this
$("#fileTreeInviati .php-file-tree .pft-directory li").each(function(){
$(this).children("a").each(function(i,e){
if ($(e).hasClass("new")){
cont++;
console.log($(e).text());
$(this).parent().parent().parent().children("a").children("span").text(cont);
}
})
cont = 0;
});
I think I'm almost there but the counter is always 1. I think there is something mess with .children, maybe it can handle only the first occurrence?
Thanks for help
Why not just use .length instead?
$('#fileTreeInviati .php-file-tree .pft-directory li a.new').length;
Update: If you want to count every li element separately, use this:
$('#fileTreeInviati .php-file-tree .pft-directory li').each(function() {
alert($('a.new', this).length);
})
OK, I figure out how to do the magic:)
Here it is:
cont = 0;
$('#fileTreeInviati .php-file-tree .pft-directory').each(function() {
$(this).children("ul").children("li").children("a.new").each(function(i,e){
cont++;
$(e).parent().parent().parent().children("a").children("span").text(cont);
});
cont=0;
});
Now all works perfect. If you think this can do in a better way, lemme know.
Bye