The website I'm trying to scrape is https://hitbtc.com/market-overview/overview.
I am trying to get cryptocurrency coin pairs from the page by accessing the following html (and other similar html for other coin pairs):
<div class="ReactVirtualized__Table__row ReactVirtualized__Row__odd ReactVirtualized__Table__row ReactVirtualized__Row__odd animation__redToWhite--2EMEW" role="row" style="height: 30px; left: 0px; position: absolute; top: 0px; width: 1202px; overflow: hidden; padding-right: 0px;">
<div class="ReactVirtualized__Table__rowColumn" role="gridcell" style="flex: 0 1 200px; overflow: hidden;">
**BTC/USDT**
</div>
<div class="ReactVirtualized__Table__rowColumn" role="gridcell" style="flex: 0 1 200px; overflow: hidden;">
<div>
<div class="styles__imgUp--1O8Kn"></div>
1.92%
</div>
</div>
<div class="ReactVirtualized__Table__rowColumn" role="gridcell" title="₮ 59 843 794" style="flex: 0 1 200px; overflow: hidden;">₮ 59 843 794</div>
<div class="ReactVirtualized__Table__rowColumn" role="gridcell" title="₮ 6780.73" style="flex: 0 1 200px; overflow: hidden;">₮ 6780.73</div>
<div class="ReactVirtualized__Table__rowColumn" role="gridcell" title="₮ 6486.82" style="flex: 0 1 200px; overflow: hidden;">₮ 6486.82</div>
<div class="ReactVirtualized__Table__rowColumn" role="gridcell" title="₮ 6833.25" style="flex: 0 1 220px; overflow: hidden;">₮ 6833.25</div>
</div>
I want to get the text from the first tag, which should give me "BTC/USDT". I found that by using Selenium's Driver.FindElements() I would only get the first 29 elements (i.e. the ones that are displayed without doing any scrolling). Because of this I tried implementing a do-while loop to scroll down the page, obtaining element lists and appending them to a master list until the previously obtained list is the same as the current list (bottom of the page reached). Here is my code:
List<IWebElement> totalElemList = new List<IWebElement>();
List<IWebElement> elementList = new List<IWebElement>();
List<IWebElement> prevList = new List<IWebElement>();
do
{
prevList.Clear();
prevList.AddRange(elementList);
totalElemList.AddRange(prevList);
var infoList = RetryingFind(By.ClassName("ReactVirtualized__Table__row"));
foreach (var element in infoList)
{
elementList.Add(element.FindElement(By.TagName("a")));
}
Thread.Sleep(10000);
((IJavaScriptExecutor)Browser.Driver).ExecuteScript("arguments[0].scrollIntoView(true);", elementList[elementList.Count - 1]);
}
while (prevList != elementList);
However, elementList is not getting populated with any elements for some reason. I added the Thread.Sleep() trying different sleep times up to 10 sec but it didn't fix the issue. Then the ExecuteScript() line fails because it's trying to access index -1 of elementList, since its Count is 0.
I'm having trouble understanding why I was able to populate the element list before with at least some of the elements on the page, but when I use the do-while loop I get nothing. Any thoughts?
It should ideally work with scroll. Check if there is any job event being triggered when you scroll. If so, try to invoke that function from IJavaScripExecutor. That should also load you with your elements.
Related
This is the textarea. I want to send value there but. There isnt name or id. I couldnt send value.
<div id="cke_1_contents" class="cke_contents cke_reset" role="presentation" style="height: 300px;">
<textarea style="width: 100%; height: 100%; resize: none; outline: currentcolor none medium; text-align: left; -moz-tab-size: 4;" dir="ltr" class="cke_source cke_reset cke_enable_context_menu cke_editable cke_editable_themed cke_contents_rtl" tabindex="0" role="textbox" aria-multiline="true" aria-label="ویرایشگر متن غنی, txtPostContent" title="ویرایشگر متن غنی, txtPostContent"></textarea>
</div>
you can set the value of textarea inside the WebBrowser component by executing the below code
//get the main div HTML element by ID
var cke1ContentsElements = webBrowser1.Document.GetElementById("cke_1_contents");
//from main div select all HTML elements with the tag name "textarea"
var cke1TextareaList = cke1ContentsElements.GetElementsByTagName("textarea");
//from the selected list of items set value attribute for first element
cke1TextareaList[0].SetAttribute("value", "Send This String To TextArea ");
I m using iframe to open another webservice. there user can view the complete the nav of the targeted link. but i wan't to prevent the user to view the complete nav.
There are five items in the targetd URL like this:
Overview
Call Log
Terrif
Payment
Logout
<iframe id="subframe" frameborder="0" scrolling="no" src="login.aspx" style="float: left;height: 754px; margin-left: 118px; width: 727px;" ></iframe>
Now what i want is that, allow user only to view the Call Log.
How could be this possible to do?
Which steps could be taken to perform these all?
If the service is on your own domain, you can access the frames DOM like so:
var myFrame = frames["myFrame"]
var cssLink = document.createElement("link")
cssLink.href = "iframeStyles.css"; /* change this to the url for a stylesheet targetting the iframe */
cssLink .rel = "stylesheet";
cssLink .type = "text/css";
frames['myFrame'].document.body.appendChild(cssLink);
Also see this question:
How to add CSS class and control elements inside of the Iframe using javaScript.?
If the iframe loads a page from another domain, you may not alter it, because that would be against the same origin policy.
I used this a couple of months before.. Some edits might be required:
<div id="IframeWrapper">
<div id="iframeBlocker">
</div>
<iframe id="mainframe" src="http://www.xyz.com/"></iframe>
</div>
CSS:-
#IframeWrapper
{
position: relative;
}
#iframeBlocker
{
position: absolute;
top: 0;
left: 0;
width: 700px;
height: 450px;
}
#mainframe
{
overflow: hidden;
border-width: 0px;
}
OTHER ALTERNATE AND A BETTER ONE
I have this asp.net code:
#foreach( var database in Model)
{
if (!(firstTime == database.DB))
{
<h3> #database.DB </h3>
}
<div class="logContainer" onclick="location.href='/logs/Details?databaseID=#database.DB&exceptionName=#database.Exception&exceptionsOccurred=#database.Count';">
<div class="counter"><b>#database.Count</b></div>
<div class="exceptionName"> Exceptions of Type: #database.Exception</div>
<div class="date">Siste: #database.LastOccurred</div>
<hr /> </div>
firstTime = database.DB;
}
And this CSS:
.logContainer
{
width:500px;
}
.logContainer:hover
{
cursor:pointer;
background-color:#ffffcc;
}
.counter {
height: 30px;
width:35px;
float:left;
background: none repeat scroll 0 0 #E6FFDC;
border: 1px solid #BBDD66;
text-align:center;
vertical-align:middle;
line-height:1.5em;
font-size:1.5em;
}
.exceptionName
{
width:200px;
display:inline;
padding-left: 10px;
display: inline;
}
.date
{
font-size: 0.9em;
color:gray;
width:200px;
padding-left: 47px;
}
What it does is to display the ouput row per row, and when the Dabase.DB changes it writes it and start again.
What I want is to display the output horizontally having 3 logcontainer per row, and if I encounter a new database.DB break it, write the name of the database and start from the left.
How should I do modify the code to do it?
Just make your .logcontainer float to the left, and every 3 display, clear the floating.
currentCol = 0
#foreach( var database in Model)
{
if (!(firstTime == database.DB))
{
<h3> #database.DB </h3>
currentCol = 0
}
<div class="logContainer" onclick="location.href='/logs/Details?databaseID=#database.DB&exceptionName=#database.Exception&exceptionsOccurred=#database.Count';">
<div class="counter"><b>#database.Count</b></div>
<div class="exceptionName"> Exceptions of Type: #database.Exception</div>
<div class="date">Siste: #database.LastOccurred</div>
</div>
currentCol += 1;
if (currentCol = 2) { //3 columns were displayed, switch row
currentCol = 0;
<br style="clear:both" />
}
firstTime = database.DB;
}
CSS :
.logContainer
{
width:500px;
float:left;
}
note: if the parent container of .logContainer is less than 1500px wide, you'll end up with a row of 2 columns followed by a row of 1 column.
i have written one javascript function to retrieve the position of a button and assigned it to asp:updateprogress but i want to apply the button's position to div element in the code or a label control within the updateprogress not to update progress.
<asp:UpdateProgress ID="UpdateProgress2"
runat="server"
AssociatedUpdatePanelID="SendMailUpdatePanel"
DisplayAfter="0">
<ProgressTemplate>
<div id="blur" style="top: 0px; left: 0px; width: 99%; height: 5000px; position: absolute;background-color: white; z-index: 999; filter: alpha(opacity=50); opacity: 0.5;-moz-opacity: 0.85; padding-top: 25%; padding-left: 30%;" />
<div id="progress" style="text-align: center; width: 444px; border: 1px solid black;padding: 10px; background-color: #eee; z-index: 998; filter: alpha(opacity=500);-moz-opacity: 1.00;">
<b>Mail is being Sent! Please Wait...</b>
<br />
<asp:Image ID="LoadImage"
runat="server"
ImageUrl="~/Images/spinner.gif" />
<br />
</div>
</ProgressTemplate>
</asp:UpdateProgress>
My javascript function is:
function getPosition(btnSendResume, progress)
{
var btnSendRe = document.getElementById(btnSendResume);
var divp = document.getElementById(progress);
divp.style.display="block";
divp.style.left=btnSendRe.offsetLeft;
divp.style.top=btnSendRe.offsetTop + btnSendRe.offsetHeight - 40;
}
I have written following under button click:
btnSendResume.Attributes.Add("onclick", "getPosition('" + btnSendResume.ClientID + "','" + UpdateProgress2.FindControl(progress).ClientID + "');");
But it is giving error that progress doesn't exist under the current context.
Your <div id="progress" is a normal HTML element, not a server-side control.
You should just write document.getElementById("progress").
You can do this by Jquery.
A simple offset() will return left and top position of a control.
function getPosition(btnSendResume, progress)
{
var btnSendReOffset = $('#btnSendResume').offset();
var btnSendRe = $('#btnSendResume');
var divp = document.getElementById(progress);
divp.style.display="block";
divp.style.left=btnSendReOffset.left;
divp.style.top=btnSendReOffset.top+ btnSendRe.height() - 40;
}
You can add a click event to your button on window load and trigger your function.
One of gridview's column is a "Content" column that can have few lines of text (it can be literal, textbox or label ).
In "default" mode i want it to show only the first line and a link button: "(more)" or "(read)".
Clicking on this link should expand the column and display full content.
What is the best way to do this?
Selecting first 10 characters of content text and using it as your link's text is better aproach. This will reduce size of data that retrieved from database like that :
SELECT ContentId, SUBSTRING(Content, 0, 10) AS Content
FROM ContentTable;
Then you can use template column for this column that includes a label and a link. Lbel for the description text, link for the details.
<asp:TemplateColumn>
<ItemTemplate>
<asp:Label
Text='<%# Eval("Content") %>'
runat="server"/>
<a href='<%# Eval("ContentId", "contentdetails.aspx?id={0}") %>'>More</a>
</ItemTemplate>
</asp:TemplateColumn>
This will help you.
http://www.asp.net/community/control-gallery/Item.aspx?i=1465
try this. http://mosesofegypt.net/post/BuildingjQueryAndASPNetAJAXEnabledControlsjQueryCollapsiblePanelExtenderPart2.aspx
Use the power of CSS!
Place this inside your gridview row. It will naturally push out the row to the height of your content, or the amount of rows required.
<div class="toggle">
<div class="toggle-header">
Toggle!
</div>
<div class="toggle-height">
<div class="toggle-transform">
<p>2nd line of text</p>
<p>3rd line</p>
<p>4th line</p>
<p>etc</p>
</div>
</div>
</div>
And use this CSS...
body {
font-family: sans-serif;
}
.toggle {
position: relative;
border: 2px solid #333;
border-radius: 3px;
margin: 5px;
width: 200px;
}
.toggle-header {
margin: 0;
padding: 10px;
background-color: #333;
color: white;
text-align: center;
cursor: pointer;
}
.toggle-height {
background-color: tomato;
overflow: hidden;
transition: max-height .6s ease;
max-height: 0;
}
.toggle:hover .toggle-height {
max-height: 1000px;
}
.toggle-transform {
padding: 5px;
color: white;
transition: transform .4s ease;
transform: translateY(-100%);
}
.toggle:hover .toggle-transform {
transform: translateY(0);
}
You may want to disguise the "toggle" with a textbox of your "(more)" line to expand the rest.
Let us know if it worked.