Techniques to avoid changing CSS selectors? - css

The thing is that I am working on a web scraping project to the edreams website, and the selector that refers to the next button changes continuously. A few days ago it was:
#search_results_table > div:nth-child(2) > div > div > div > div.d7a0553560 > div.b727170def > nav > div > div.f32a99c8d1.f78c3700d2 > button > span > svg
And now it is:
#search_results_table > div:nth-child(2) > div > div > div > div.d7a0553560 > div.a826ba81c4.fa71cba65b.fa2f36ad22.afd256fc79.d08f526e0d.ed11e24d01.ef9845d4b3.b727170def > nav > div > div.f32a99c8d1.f78c3700d2 > button
This is because a part of my code is:
driver.find_element(By.CSS_SELECTOR,'#search_results_table > div:nth-child(2) > div > div > div > div.d7a0553560 > div.b727170def > nav > div > div.f32a99c8d1.f78c3700d2 > button > span > svg').click()
time.sleep(10)
So, what happens is that every time I run the code that makes the web scraping to obtain the data, there are execution errors due to the change of the css selectors.
Any technique that you know can be useful?

Related

Generic CSS selector for GTM trigger

I'm trying to create a CSS selector to be able to match the following entries (The page-top-menu):
Header menu - Menu 1
DE
#page-top-menu > div > div.menu-wrapper > ul > li.i39.dropdown.layer.item-type-1.catid-0eca5a6c6e53f281b9e0469ca3d744fd > a
EN
#page-top-menu > div > div.menu-wrapper > ul > li.i40.dropdown.layer.item-type-1.catid-0eca5a6c6e53f281b9e0469ca3d744fd > a
FR
#page-top-menu > div > div.menu-wrapper > ul > li.i28.dropdown.layer.item-type-1.catid-0eca5a6c6e53f281b9e0469ca3d744fd > a
Header menu - Menu 2
DE
#page-top-menu > div > div.menu-wrapper > ul > li.i43.dropdown.layer.item-type-2.catid-9268a9eaa067019916390b7d08113781 > a
EN
#page-top-menu > div > div.menu-wrapper > ul > li.i43.dropdown.layer.item-type-2.catid-9268a9eaa067019916390b7d08113781 > a
FR
#page-top-menu > div > div.menu-wrapper > ul > li.i40.dropdown.layer.item-type-2.catid-9268a9eaa067019916390b7d08113781 > a
As you can see, they all have this in common:
#page-top-menu > div > div.menu-wrapper > ul > li
however when I try to create the tigger based on the following selectors, nothing happens:
#page-top-menu > div > div.menu-wrapper > ul
#page-top-menu > div > div.menu-wrapper > ul > li
#page-top-menu > div > div.menu-wrapper > ul > li > *
If I use the full CSS selectors, the triggers work.
EDIT:
here is an example of one of the html elements (The highlighted part is the one the selector refers to):
Here is a snapshot of how the Tag and triggers are set up:
The problem is that your a element has child elements. And when you clicked element inside tag a it will fire click event, but click element will point to inner tag. You have two ways how to solve it:
1) Target all children elements in multi levels:
Type: Click - All Elements
CSS selector: #page-top-menu > div > div.menu-wrapper > ul > li *
2) Target only link:
Type: Click - Just Links
CSS selector: #page-top-menu > div > div.menu-wrapper > ul > li > a

How do I select this div in CSS?

The only class that I am allowed to use is .servicebox
I've tried this:
.servicebox div > div > div:last-child{
padding: 0;
}
but it is selecting more div, not the last one.
Use :last-child on the second div
.servicebox div > div:last-child > div{
padding: 0;
}
How about by id:
#c951 { /*your css*/ }
I beleive
div.servicebox > div > div > div.csc-default
should work if your last div that your are interested has a unique class. If not then:
div.servicebox > div > div > div#c951
should work.

Is there a way to group nth-child CSS rules for same parent

I have the following CSS rules:
#div .item62 > .wrap > .cont > .level1 > div:nth-child(9),
#div .item62 > .wrap > .cont > .level1 > div:nth-child(11),
#div .item62 > .wrap > .cont > .level1 > div:nth-child(n+12){
width: 140px ;
}
I would like to group those rules to make the code shorter and probably to make the code more efficient when the parent element selection would be done once(do those rules make the browser engine search three times the same "parent" element or is this already optimized?).
Is there a way to write these rules in a shorter way?
As the code structure is created by third party code I cannot add a distinct class or change HTML structure.
I could not find a CSS method that would allow to select one parent with multiple distinct child elements without rewriting the whole path to the child elements.
Also I have no additional CSS preprocessors avaliable.
Your current CSS rule is the shortest you can write without any Preprocessor available.
The expression :nth-child(n+12) matches every child starting with and including :nth-child(12). Assuming the 11 and n+12 are not typos, you can condense them to a single n+11 expression:
#div .item62 > .wrap > .cont > .level1 > div:nth-child(9),
#div .item62 > .wrap > .cont > .level1 > div:nth-child(n+11)
Notice now that :nth-child(9), :nth-child(n+11) is essentially the same as :nth-child(n+9), i.e. everything starting with and including :nth-child(9), but excluding :nth-child(10).
With this in mind, you can rewrite the above selector list using :not(:nth-child(10)):
#div .item62 > .wrap > .cont > .level1 > div:nth-child(n+9):not(:nth-child(10))
Now you have a single complex selector with a negation. I cannot comment on the performance implications of having a negation in the mix, however unless profiling shows that this selector causes significant performance issues, I'd say that for reducing your selector list by more than half the bytes, it's absolutely worth it. Personally, I can't imagine :not(:nth-child(10)) being much cheaper or much more expensive than :nth-child(n+b) for any nonzero b. Each of these is a pretty complex operation by itself.
You could do something like this, it won't be much shorter and is technically redundant.
#div > .item62 > .wrap > .cont > .level1 > div:nth-child(2n+9),
#div > .item62 > .wrap > .cont > .level1 > div:nth-child(n+12)
{
width:140px;
}

How to target a group of long similar CSS selectors on one line?

I am currently often using in my CSS things like
table.form > tbody > tr > td > input[type=text],
table.form > tbody > tr > td > input[type=password],
table.form > tbody > tr > td > textarea ,
table.form > tbody > tr > td > select {width: 300px;}
Is this a correct way to do it with respect to minimal CSS output size? Is there any way to group those elements without having to reiterate their entire parent structure, something along the lines of
table.form > tbody > tr > td >
(input[type=text],input[type=password],textarea,select) {width: 300px;}
?
Using mozilla Firefox and Webkit based web browsers, you could use :any() pseudo-class to target a group of elements at once.
The :any() pseudo-class lets you quickly construct sets of similar
selectors by establishing groups from which any of the included items
will match. This is an alternative to having to repeat the entire
selector for the one item that varies.
Mozilla Developer Network
Syntax
:-moz-any( selector[, selector]* )
:-webkit-any( selector[, selector]* )
In this particular case:
/* For FF 4+ */
table.form > tbody > tr > td > :-moz-any(input[type=text],input[type=password],textarea,select) {width: 300px;}
/* For Chrome 12+, Safari 5.1.3+ */
table.form > tbody > tr > td > :-webkit-any(input[type=text],input[type=password],textarea,select) {width: 300px;}
EXAMPLE HERE
This is an experimental technology that is in progress to be standardized in CSS Selectors Level 4 under the name :matches().

Hover submenu in IE6

I am developing web with wordpress and have a problem with it's submenu. The problem is that it doesn't appear with hover on IE6. There must be something wrong with css, i guess. Any ideas? Is this possible to be done without javascript?
as i understand the problem is with #access ul ul { display:none; } as i delete it, it shows allways the submenu.. is there ny way to change it into something?
My guess since I don't have the code is that the submenu is using li:hover to cause the submenu to appear. IE6 only supports the :hover pseudoclass on <a> tags (only a:hover will work in IE6).
Check out CSS Play for some CSS only dropdown menu examples.
Nope it is not possible without javascript at least in IE6, you need javascript for IE6 :(
Here are some options for you:
IE6 Hover Issue
I think it is possible with this simple trick (overflow-height-trick).
Note that:
A container should have real height.
A wrapper should have real height and "position:absolute".
A childs of wrapper should have real height and "position:relative".
Wrap your menu like this:
< div id="container" >
< div id="menu_wrapper >
< div id="selector" >Computed Value< / div >
< ul id="menu" >
< li >Predefined Value< / li >
< li >Predefined Value< / li >
< li >Predefined Value< / li >
< ul >
< / div >
< / div >
Set styles:
< style >
div#container{height:100%;}
div#menu_wrapper{height:32px; position:absolute;}
div#menu_wrapper:hover{height:100%;}
div#selector{height:32px;clear:both;}
ul#menu li{height:32px;}
< / style >
Enjoy )

Resources