├── .gitattributes ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── Y.png ├── css ├── content.css └── popup.css ├── manifest.json ├── scripts ├── content.js ├── events.js └── jquery-3.6.0.min.js └── views ├── popup.html └── slider.html /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | profile_template_reference.js -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Do as you please with the code with a bit of integrity I guess. 2 | 3 | ## What is required to coded? 4 | 5 | Currently, I am busy with heavy school work. So probably not going to touch this repo for long time. Education section and some other sections need scraping code. You can contribute there. 6 | 7 | Extraction for each section is carried out separately by the client/user when they perform "click" event. Each click event invokes a special function for the corresponding section. 8 | So in a sense the code is a bit modular. The majority of javascript action takes place in `content.js` file. This is where I also make use of Javascript to inject the `Slider` of the extension. 9 | 10 | The `main()` function runs all the procedures from DOM generators to eventTrigger functions. Only the `Slider` toggle procedure is run outside of `main()` which interacts with the `service_worker` file in the background to handle the click-event trigger for the slider to slide-in or out of the window view. 11 | 12 | There are some utility functions as well. Mostly concerned with scraping the data coherently. 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Draken Wan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yale3 2 | Updated and simplified version of Rekrut (Linkedin scraper for extracting profile data) 3 | 4 | Yal§ or Yale3 (pronounced as Yal-crow) is a simplified version of [Rekrut](https://github.com/DrakenWan/Rekrut). Just enable developer mode in your `chrome://extensions` tab and click on `load unpacked` button and browse to the cloned folder. Run it on linkedin website profiles. Raw JSON profile data will be displayed on a sidebar that will appear when you click on the extension icon. Remember to scroll down slowly and click on all ["show more"](#) buttons if any to correctly extract data. 5 | 6 | I have added a `Save PDF` option feature which is already a linkedin feature. Just able to access that feature in the extension's slider menu. 7 | 8 | You are free to do anything with the code on the repo. Read the [license](https://github.com/DrakenWan/Yale3/blob/main/LICENSE) 9 | 10 | 11 | ## Extraction 12 | 13 | This section has not been updated and tested in last 5 months. Basic data would still scrape absolutely but may not be clean. 14 | 15 | Section Name | Can Extract? | Clean? | Deepscan Extraction? 16 | :----------------- | :----------------- | :----------------- | :------------------ 17 | *profile data* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: 18 | *experience section*| :heavy_check_mark: | :heavy_check_mark: | :x: 19 | *education section*| :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: 20 | *certifications* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: 21 | *volunteer experience*| :x: | :x: | :x: 22 | *skills section* | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: 23 | *accomplishments* | :x: | :x: | :x: 24 | 25 | ## What is Deepscan? 26 | 27 | It is nothing but a fancy term for the functionality to scrape more data as the linkedin limits the list of content shown for each section in the profile (on average max of 3 items in a list). So you have to press on show more. This takes you to a next "DOM object" that covers entire window with full list of items in a section. So for this you have to checkmark the "deepscan" checkbox button and then as usual press on "extract
" button to get the full list of items. If you are doing the scraping on profile page for same section. Do not forget to uncheck it. 28 | 29 | ## Bug reporting 30 | I strive to make the code as general as possible but the extractor tool may not be perfect. If you find any bug on any profile please let me know in [issues](https://github.com/DrakenWan/Yale3/issues) section. 31 | 32 | Note**: If the chrome extension hangs due to some error or bug, go to `chrome://extensions` and `update` the `Yale3` extension and referh to a new linkedin profile. THis will resolve the issue. If possible you can screenshot the error you find in the `chrome://extensions` page and report it in the issue section. 33 | ## Update Timeline 34 | 35 | I will keep posting timed updates here. In future will shift these somewhere else if I have time 36 | 37 | #### Update(dated: 12th March, 2023) 38 | 39 | - The deepscan is not working for experience section. I am looking into it. won't take much time to fix it. 40 | 41 | #### Update(dated: 20th February, 2023) 42 | 43 | - Completed the code for education section extraction. I have tested it only on one profile. Need to test on other profiles too. You may notice the code has been recycled from the `extractCert` method. LinkedIn has made their HTML document very consistent in last update. Most of the anchor part of the code can be simply copied from any of the other sections. Can make some of these common variables common for these different manual extraction methods but it will be cumbersome. 44 | 45 | 46 | #### Update(dated: 29th December, 2022) 47 | 48 | - I have fixed the extraction of `experience section`. It is working fine for 30 LinkedIn profile pages I verified it with. 49 | - I have added a `clear text` button to clear textbox content. 50 | - Removed the old, redundant code with new code or deleted it entirely. 51 | - Will start working on writing code for scraping other sections that are left. 52 | 53 | (second update) 54 | - Added a save profile data button that consolidates profile data textboxes' values into a text file. Prompts user to name the file. 55 | 56 | #### Update(dated: 27th December, 2022) 57 | 58 | Apparently, the HTML code for `experience section` has been changed by a slight. But that is huge since experience section was hardest to generalize for me. It will take time to make further correction to it. The deepscan extraction still works for this section since the HTML document for all of them new pages is same and not changed. 59 | 60 | I am going to start working on extracting the other sections of the linkedin profile. I noticed that a lot of redundant code has been left by me and which might mislead some of you (who dive into the code) into thinking some of this redundant code is being used which is not the case. I will start in removing some of this redundant code with small minor updates. Some of that code might be useful so I will take my time in removing it. Most of the old Yale3 code has been replaced by new one in commits I believe I made around mid-August of 2022. It was when I migrated the extension from manifest v2 to v3. 61 | 62 | #### Update(dated: 12th November, 2022) 63 | 64 | Some minor error fixing due to HTML changes. Currently not able to conceive extraction codes for remaining sections due to heavy school schedule. Feel free to contribute if anyone wants to. I will try to create codes for them asap 65 | 66 | #### Update(dated: 16th August, 2022) 67 | 68 | Added experience extraction through manual selection. Look for bugs if any. Only test on five profiles on LinkedIn. Still looking for errors by testing it on various LinkedIn profile. If I find any errors, I will fix them asap. 69 | 70 | #### Update (dated: 15th August, 2022) 71 | 72 | Added skills extraction. Changed the UI a bit. The UI is still ugly. If someone wants to help with it they are more than welcome. 73 | 74 | #### Update (dated: 14th August, 2022) 75 | 76 | I have added a button to manually extract certifications. I have not been able to get any errors using this `manual feature` on the 10 standard reference LinkedIn profiles while coding it. The manual extraction utility includes a **deepscan** feature. If a section has more than three items in its list then the user can click on *deepscan checkbox* and click on the _show more arrow_ to open the new page with the entire list of items of the section and then press the `extract {section name}` button. Experiment around with the feature and you will understand how it works. I will add this feature one-by-one for all sections for easier scraping of profile data. 77 | 78 | 79 | #### Update (dated: 30th July, 2022) 80 | 81 | I have migrated the manifest version from 2 to 3 for the extension. The version of Yalcrow has been changed to 2.0.0 starting from this readme commit. There are some errors that occured in doing so that I have mentioned in the description of last [commit](https://github.com/DrakenWan/Yale3/commit/af96ff1b5589b70a246e5112a0ebc4aa57cae443). But these errors do not jeopardise the extraction tool and it will still work on a linkedin profile page to extract the sections that are tickmarked in the aforementioned section. 82 | 83 | 84 | I am going to start working on adding a few extensible features and I am going to completely change the way the extraction tool works as well. Currently, the extraction tool is initiated by scrolling the profile page but I will add buttons for each separate section to perform the extraction separately and manually at the click of a button. For now that seems to be the only possible solution in my mind to perform scraping with no conflicts. 85 | 86 | 87 | 88 | #### Update (dated: 9th January, 2022) 89 | 90 | LinkedIn has made drastic changes to the way profile data is loaded. I have been quite busy with work lately. Not all sections can be extracted due to major document tag changes as well as the way the profile now interacts with user actions. Clicking on 'Show More *' buttons takes you away to an entirely different document. I will try to amend this asap. 91 | 92 | -------------------------------------------------------------------------------- /Y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KartikayKaul/Yale3/efd0a6b6cf4c739e8f37230ddba190cd6f81d16e/Y.png -------------------------------------------------------------------------------- /css/content.css: -------------------------------------------------------------------------------- 1 | #slider { 2 | position: fixed; 3 | z-index: 9000000000000000000; 4 | top: 0px; 5 | right: 0px; 6 | 7 | background-color : cornflowerblue; 8 | width : 0px; 9 | transition: 0.4s; 10 | 11 | height: 100vh; 12 | overflow-y : auto; 13 | } 14 | 15 | 16 | /* Slider header, footer and body tags below */ 17 | /* add css stylesheets for slider child elements below*/ 18 | #sheader { 19 | position: sticky; 20 | top: 0; 21 | padding: 20px; 22 | background-color: #052536; 23 | text-align:center; 24 | z-index: 5; 25 | box-shadow: 0 0 5px #052536; 26 | } 27 | 28 | #sheader > div > h1, #sfooter > h2 { 29 | color: white !important; 30 | } 31 | 32 | #sbodycontainer { 33 | color: white; 34 | } 35 | 36 | #sfooter { 37 | position: sticky; 38 | bottom: 0; 39 | background-color: #052536; 40 | text-align: center; 41 | z-index: 5; 42 | box-shadow: 0 0 10px #052536; 43 | } 44 | 45 | #extractBtn, #savepdf { 46 | 47 | border-radius: 4px; 48 | background-color: #0077b5; 49 | border: none; 50 | color: #FFFFFF; 51 | text-align: center; 52 | font-size: 28px; 53 | padding: 5px; 54 | width: 200px; 55 | transition: all 0.5s; 56 | cursor: pointer; 57 | margin: 5px; 58 | opacity: 0.8; 59 | 60 | /* positioning on window */ 61 | position: relative; 62 | } 63 | 64 | #extractBtn:hover, #savepdf:hover { 65 | background-color: #035b8a; 66 | border-right: 2px solid grey; 67 | border-bottom: 2px solid grey; 68 | } 69 | 70 | /* The extract buttons inside of slider */ 71 | .internal_button { 72 | display: inline-block; 73 | padding: 15px 25px; 74 | font-size: 24px; 75 | cursor: pointer; 76 | text-align: center; 77 | text-decoration: none; 78 | outline: none; 79 | color: #fff; 80 | background-color: #0077b5; 81 | border: none; 82 | border-radius: 15px; 83 | box-shadow: 0 9px #999; 84 | } 85 | 86 | .internal_button:hover {background-color: #035b8a} 87 | 88 | .internal_button:active { 89 | background-color: #035b8a; 90 | box-shadow: 0 5px #666; 91 | transform: translateY(4px); 92 | } 93 | 94 | .sticky_buttons { 95 | position: sticky; 96 | display: block; 97 | font-size: 16px; 98 | margin: 15px 25px 0px 15px;; 99 | } 100 | 101 | #deepscan { 102 | padding: 10px; 103 | opacity: 100% !important; 104 | } 105 | 106 | #deepscancontainer { 107 | position: sticky !important; 108 | z-index: 5; 109 | } 110 | 111 | #deepscanlabel { 112 | color: white; 113 | padding: 15px; 114 | border: 1px solid rgb(100, 237, 223); 115 | } 116 | 117 | textarea { 118 | margin: 1px; 119 | padding-right: 20px; 120 | border: 2px solid black; 121 | height: 250px !important; 122 | 123 | } 124 | 125 | textarea:hover { 126 | background-color: rgb(178, 197, 231); 127 | border: 2px solid rgb(27, 15, 49); 128 | } -------------------------------------------------------------------------------- /css/popup.css: -------------------------------------------------------------------------------- 1 | body { 2 | float: left; 3 | padding: 10px; 4 | width: 200px; 5 | background-color: lightgoldenrodyellow; 6 | border: 2px solid cornflowerblue; 7 | } -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"Yal§", 3 | "version": "2.0.2", 4 | "manifest_version": 3, 5 | "icons": { 6 | "128": "Y.png" 7 | }, 8 | "action" : { 9 | "default_title": "yale3" 10 | }, 11 | 12 | "background": { 13 | "service_worker": "./scripts/events.js" 14 | }, 15 | 16 | "content_scripts": [ 17 | { 18 | "matches": ["https://*.linkedin.com/*"], 19 | "css": ["./css/content.css"], 20 | "js": ["./scripts/jquery-3.6.0.min.js","./scripts/content.js"] 21 | } 22 | ], 23 | 24 | "permissions": [ 25 | "tabs", 26 | "storage", 27 | "activeTab" 28 | ], 29 | 30 | "web_accessible_resources": [{ 31 | "resources": ["./views/slider.html", "./scripts/jquery-3.6.0.min.js"], 32 | "matches": [""] 33 | }], 34 | 35 | "homepage_url": "https://github.com/drakenwan/" 36 | } -------------------------------------------------------------------------------- /scripts/content.js: -------------------------------------------------------------------------------- 1 | //alert("I am on a profile page"); 2 | 3 | //global imports (avoid these) 4 | 5 | 6 | /////////////// * ---- GLOBAL VARIABLES ---- * ///////////////// 7 | var url = ""; 8 | const todoresp = {todo: "showPageAction"}; 9 | 10 | ///////////// * GLOBAL VARIABLES ENDS HERES * ///////////////// 11 | 12 | 13 | //invoked main driver function 14 | chrome.runtime.sendMessage(todoresp); 15 | main(); 16 | 17 | 18 | 19 | 20 | //trigger different functionalities in main functions 21 | function main() { 22 | 23 | ///////// VARIABLES ////////// 24 | // define any VARIABLES below here 25 | 26 | 27 | 28 | // Edit this string to edit the slider popup 29 | /* 30 | NOTE: Unable to access the slider.html file even after using troubleshoot 31 | steps from google. So I am using the content script to inject the 32 | slider file into the webpage. 33 | */ 34 | // (appears on clicking extension 35 | // icon) 36 | var sliderInnerHTMLString = "\ 37 | \ 38 |
\ 39 |
\ 40 |
\ 41 | \ 42 |
\ 43 |
Clear Text?
\ 44 |
\ 45 |
\ 46 |
\ 47 | \ 48 | \ 49 | \ 50 |
\ 51 |
\ 52 |
\ 53 | This textbox extracts if you scroll the slider menu.\ 54 | \ 55 |
\ 56 |

Education Section

\ 57 |
\ 58 | \ 59 |
\ 60 |
Extract Education
\ 61 |
\ 62 | \ 63 |

Experience Section

\ 64 | \ 65 | \ 66 |
\ 67 |
Extract Work Ex
\ 68 |
\ 69 |

Licenses and Certifications

\ 70 |
\ 71 | \ 72 |
\ 73 |
Extract Certifications
\ 74 | \ 75 |
\ 76 |

Skills

\ 77 |
\ 78 | \ 79 |
\ 80 |
Extract Skills
\ 81 |
Save PDF
\ 82 |
\ 83 | \ 84 | \ 85 | \ 86 |

\ 87 |
Save Profile Data
\ 88 |
\ 89 | "; 90 | 91 | //////////VARIABLES END/////////// 92 | 93 | 94 | 95 | // generate the DOM nodes below // 96 | 97 | sliderGen(sliderInnerHTMLString); 98 | 99 | // DOM node generators above // 100 | 101 | 102 | //listener to trigger action - which is to push in/out 103 | //the slider toggle works with the service_worker file 104 | chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { 105 | if(msg.todo == "toggle") { 106 | slider(); 107 | } 108 | }); 109 | 110 | 111 | //run savePDF option 112 | document.getElementById('savepdf').addEventListener("click", savePDF); 113 | 114 | //Clear text button action 115 | document.getElementById('clear_text_button').addEventListener("click", function() { 116 | var ids = ['basicprofile', 'educationtext', 'experiencetext', 'skillstext', 'certificationstext' ]; 117 | for(var i=0; i div > h1') || document?.getElementsByClassName('artdeco-entity-lockup__title ember-view')[0] || null; 179 | uname = uname?.textContent || ""; 180 | uname = getCleanText(uname); 181 | document.getElementById('slider').querySelector('#sheaderheader').innerHTML = "

" + uname + "

"; 182 | } 183 | 184 | //slider window element generator 185 | function sliderGen(sliderInnerHTMLString) { 186 | var slider = document.createElement("div"); 187 | slider.id = "slider"; 188 | var sliderDivInnerHTML = sliderInnerHTMLString; 189 | 190 | slider.innerHTML += sliderDivInnerHTML; 191 | 192 | document.body.prepend(slider); 193 | } 194 | 195 | //slider function to toggle the slider frame 196 | function slider() { 197 | var slider = document.getElementById("slider"); 198 | 199 | var styler = slider.style; 200 | //alert("slider" + slider); 201 | 202 | //toggle slider 203 | if(styler.width == "0px") { 204 | styler.width = "400px"; 205 | } else { 206 | styler.width = "0px"; 207 | } 208 | } 209 | 210 | //module for extracting the details 211 | function extract() { 212 | // retreiving profile Section data 213 | const profileSection = document.querySelector(".pv-top-card"); 214 | 215 | const fullNameElement = profileSection?.querySelector('h1') 216 | const fullName = fullNameElement?.textContent || null 217 | 218 | const titleElement = profileSection?.querySelector('.text-body-medium') 219 | var title = titleElement?.textContent || null 220 | 221 | var tbs = profileSection?.querySelectorAll(".text-body-small") 222 | const locationElement = ((tbs) ? tbs[1] : null) 223 | var loc = locationElement?.textContent || null 224 | 225 | const photoElement = document.querySelector(".pv-top-card-profile-picture__image") || profileSection?.querySelector('.profile-photo-edit__preview') 226 | const photo = photoElement?.getAttribute('src') || null 227 | 228 | const descriptionElement = document.querySelector('div#about')?.parentElement.querySelector('.pv-shared-text-with-see-more > div > span.visually-hidden')// Is outside "profileSection" 229 | var description = descriptionElement?.textContent || null 230 | 231 | const url = window.location.url; 232 | var rawProfileData = { 233 | fullName, 234 | title, 235 | loc, 236 | photo, 237 | description, 238 | url 239 | } 240 | 241 | var profileData = { 242 | fullName: getCleanText(rawProfileData.fullName), 243 | title: getCleanText(rawProfileData.title), 244 | location: getCleanText(rawProfileData.loc), 245 | description: getCleanText(rawProfileData.description), 246 | photo: rawProfileData.photo, 247 | url: rawProfileData.url 248 | } 249 | ///extraction of profile data ends here/// 250 | 251 | return profileData; 252 | }//Extract() functions ends here 253 | 254 | 255 | // Extract license and certifications 256 | function extractCert() { 257 | var anchor1 = document.getElementById('licenses_and_certifications'); 258 | var anchor2 = document.querySelector('.pvs-list'); 259 | 260 | var list = null; 261 | var certs = []; 262 | 263 | 264 | if(anchor1) { 265 | anchor1 = anchor1.nextElementSibling.nextElementSibling 266 | list = anchor1.querySelector('ul').children; 267 | } 268 | 269 | if(anchor2 && document.getElementById('deepscan').checked && location.href.includes('certifications')) { 270 | list = anchor2.children; 271 | } 272 | 273 | if(list) { //if the anchor exists 274 | for(i=0; i div').firstElementChild.nextElementSibling; 297 | firstdiv = elem.firstElementChild.firstElementChild.children; 298 | 299 | url = elem.firstElementChild.nextElementSibling?.querySelector('a').href || ""; 300 | } //if anchor2 301 | else { 302 | break; 303 | } 304 | 305 | //var condn = (firstdiv.querySelector('a'))? 'a >' : ''; 306 | var name = getCleanText(firstdiv[0].querySelector('span > span')?.textContent || ""); 307 | var issuedby = getCleanText(firstdiv[1].querySelector('span > span')?.textContent || ""); 308 | var issuedon = getCleanText(firstdiv[2]?.querySelector('span > span')?.textContent || ""); 309 | var expiration = issuedon? issuedon.split('·')[1] : ""; 310 | var issuedon = issuedon? issuedon.split('·')[0]?.split('Issued ')[1] || "" : ""; 311 | 312 | 313 | 314 | var temp = { 315 | 'id': i, 316 | 'title': name, 317 | 'issuer':issuedby, 318 | 'date':issuedon, 319 | 'expiration': expiration, 320 | 'link': url 321 | }; 322 | 323 | certs.push(temp); 324 | 325 | } //for loop to scrape through the list 326 | } 327 | var objtemp = { 328 | 'name': 'licenses', 329 | 'data': certs 330 | } 331 | 332 | document.getElementById('certificationstext').value = JSON.stringify(objtemp); 333 | } //license extraction ends here 334 | 335 | 336 | // Extract Skills 337 | function extractSkills() { 338 | 339 | //defining anchors (roots from where scraping starts) 340 | var anchor1 = document.getElementById("skills"); 341 | var anchor2 = document.querySelector('.pvs-list'); 342 | 343 | var list = null; 344 | var skills = []; 345 | 346 | if(anchor1 && !document.getElementById('deepscan').checked) { 347 | anchor1 = anchor1.nextElementSibling.nextElementSibling 348 | list = anchor1.querySelector('ul').children; 349 | } 350 | 351 | if(anchor2 && document.getElementById('deepscan').checked && location.href.includes('skills')) { 352 | list = anchor2.children; 353 | } 354 | 355 | if(list) { //if the anchor exists 356 | for(i=0; i span > span').textContent || ""); 367 | 368 | 369 | }// anchor1 ends here 370 | else if ((anchor1 == null) && anchor2 && document.getElementById('deepscan').checked && 371 | location.href.includes('skills')) { 372 | elem = list[i].querySelector('div > div').firstElementChild.nextElementSibling; 373 | elem = elem.firstElementChild.firstElementChild.children; 374 | 375 | elem = getCleanText(elem[0]?.querySelector('div > span > span').textContent || ""); 376 | 377 | } //anchor2 ends here 378 | else { //exit 379 | break; 380 | } 381 | 382 | skills.push( 383 | { 384 | 'id': i, 385 | 'title': elem 386 | } 387 | ); 388 | } //for loop 389 | 390 | 391 | } //if `the list from anchor exists` condn ends here 392 | 393 | 394 | var objtemp = { 395 | 'name': 'skills', 396 | 'data': skills 397 | }; 398 | 399 | document.getElementById('skillstext').value = JSON.stringify(objtemp); 400 | } //Extraction of skills ends here 401 | 402 | 403 | 404 | 405 | 406 | // Extract Experience ///// 407 | 408 | function extractExperience() { 409 | //defining anchors (roots from where scraping starts) 410 | var anchor1 = document.getElementById("experience"); 411 | var anchor2 = document.querySelector('.pvs-list'); 412 | 413 | var list = null; 414 | var exp = {}; 415 | var roles = []; 416 | var company = ""; 417 | 418 | if(anchor1 && !document.getElementById('deepscan').checked) { 419 | anchor1 = anchor1.nextElementSibling.nextElementSibling 420 | list = anchor1.querySelector('ul').children; 421 | } 422 | 423 | if(anchor2 && document.getElementById('deepscan').checked && location.href.includes('experience')) { 424 | list = anchor2.children; 425 | } 426 | 427 | 428 | 429 | if(list) { //if the anchor exists 430 | for(i=0; i div').nextElementSibling; //for anchor 1 438 | if(elem.querySelector('div > a')) { 439 | // condition for multiple roles in same company 440 | company = elem.querySelector('div > a > div > span > span')?.textContent || ""; 441 | company = getCleanText(company); 442 | 443 | elem = elem.firstElementChild.nextElementSibling; 444 | var elems = elem.querySelector('ul').children 445 | 446 | for(j=0; j < elems.length; j++) { 447 | // traversing roles list in a company 448 | 449 | var keke = elems[j].querySelector("div > div")?.nextElementSibling || null; 450 | keke = keke?.querySelector('div > a') || null; 451 | 452 | kchilds = keke.children; 453 | var rname=" ", startDate=" ", endDate=" ", loc=" "; 454 | for(k=0; k span').textContent || ""; 459 | if(k==1) //role duration 460 | { 461 | var ta = kchilds[k].querySelector('span').textContent.split(/[-·]/); 462 | startDate = ta[0]; 463 | endDate = ta[1]; 464 | } 465 | if(k==2) //role location 466 | loc= kchilds[k].querySelector('span')?.textContent || ""; 467 | 468 | } //kloop 469 | 470 | roles.push({ 471 | 'id': j, 472 | 'title': getCleanText(rname), 473 | 'startDate': getCleanText(startDate), 474 | 'endDate': getCleanText(endDate), 475 | 'location': getCleanText(loc) 476 | }); 477 | 478 | } // role traversal loop 479 | 480 | 481 | } else { //condition when single role in one company 482 | elem = elem.querySelector('div > div > div > div'); 483 | 484 | echilds = elem.children; 485 | var rname=" ", startDate=" ", endDate=" ", loc=" "; 486 | for(k=0; k span').textContent || ""; 491 | if(k==2) //role duration 492 | { 493 | var ta = echilds[k].querySelector('span').textContent.split(/[-·]/); 494 | startDate = ta[0]; 495 | endDate = ta[1]; 496 | } 497 | if(k==3) //role location 498 | loc = echilds[k].querySelector('span')?.textContent || ""; 499 | 500 | if(k==1) //role company title 501 | company = echilds[k].querySelector('span')?.textContent || ""; 502 | if(company) 503 | company = company.split(/[-·]/)[0]; 504 | } //kloop 505 | 506 | 507 | roles.push({ 508 | 'id': 0, 509 | 'title': getCleanText(rname), 510 | 'startDate': getCleanText(startDate), 511 | 'endDate': getCleanText(endDate), 512 | 'location': getCleanText(loc) 513 | }); 514 | 515 | 516 | 517 | } //single role else condn ends 518 | 519 | 520 | exp[i] ={ 521 | 'company': company, 522 | 'roles': roles 523 | }; 524 | 525 | }//for loop over 'i' for each item in anchor list 526 | } // if list anchor exists condition 527 | 528 | document.getElementById('experiencetext').value = JSON.stringify(exp); 529 | } //extract experience ends here 530 | 531 | 532 | // Extract Experience // 533 | 534 | function extractEducation(){ 535 | //defining anchors (roots from where scraping starts) 536 | var anchor1 = document.getElementById('education'); 537 | var anchor2 = document.querySelector('.pvs-list'); 538 | 539 | var list = null; 540 | var education = []; 541 | 542 | 543 | if(anchor1) { 544 | anchor1 = anchor1.nextElementSibling.nextElementSibling 545 | list = anchor1.querySelector('ul').children; 546 | } 547 | 548 | if(anchor2 && document.getElementById('deepscan').checked && location.href.includes('education')) { 549 | list = anchor2.children; 550 | } 551 | 552 | if(list) { //if the anchor exists 553 | for(i=0; i div').firstElementChild.nextElementSibling; 574 | firstdiv = elem.firstElementChild.firstElementChild.children; 575 | 576 | 577 | } //if anchor2 578 | else { 579 | break; 580 | } 581 | 582 | 583 | var institute_name = getCleanText(firstdiv[0].querySelector('span > span')?.textContent || ""); 584 | var degree = getCleanText(firstdiv[1].querySelector('span > span')?.textContent || ""); 585 | var start = getCleanText(firstdiv[2]?.querySelector('span > span')?.textContent.split('-')[0] || ""); 586 | var end = getCleanText(firstdiv[2]?.querySelector('span > span')?.textContent.split('-')[1] || ""); 587 | var grade = getCleanText(elem?.firstElementChild?.nextElementSibling?.querySelector('ul > li >div > div > div >div >div')?.textContent.split(':')[2] || ""); 588 | 589 | 590 | 591 | var temp = { 592 | 'id': i, 593 | 'name': institute_name, 594 | 'degree': degree, 595 | 'start_date': start, 596 | 'end_data': end, 597 | 'grade': grade 598 | }; 599 | 600 | education.push(temp); 601 | 602 | } //for loop to scrape through the list 603 | } 604 | var objtemp = { 605 | 'name': 'education', 606 | 'data': education 607 | } 608 | 609 | document.getElementById('educationtext').value = JSON.stringify(objtemp); 610 | 611 | } //extract education ends here 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | //////////// *---- UTILS -----* ////////////// 623 | // Utility functions 624 | 625 | // Save PDF document of a linkedinProfile 626 | function savePDF() { 627 | var spanList = document.getElementsByTagName("span"); 628 | var m = []; 629 | 630 | for(i=0; i+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 2 | 3 | 4 | Ext13 5 | 6 | 7 | 8 | 9 |

10 | please refresh the webpage for changes to take effect. 11 |

12 |
13 |

Extract Profile

14 |

Toggle

15 |

To extract a profile, click on the "extract" button 16 | on the bottom right of the window. 17 | 18 | To properly extract the details, click on the show more buttons 19 | of each section (Education, Certifications, etc.) before you press extract. 20 | You can press extract button as many times as you like. 21 |

22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /views/slider.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Slider 5 | 6 | 7 |

My ancestors say whatsup!

8 | 9 | --------------------------------------------------------------------------------