2024-02-10 03:42:44 +00:00
<!DOCTYPE html>
< html class = "no-js" lang = "en" >
< head >
< title > WebDriverAbstract - RSS-Bridge< / title >
< meta name = "description" content = "The RSS feed for websites missing it" >
< meta name = "author" content = "RSS-Bridge Contributors" >
< meta charset = "UTF-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< link rel = "icon" href = "../themes/daux/img/favicon-blue.png" type = "image/x-icon" >
<!-- Mobile -->
< meta name = "apple-mobile-web-app-capable" content = "yes" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
<!-- JS -->
< script >
window.base_url = "../";
document.documentElement.classList.remove('no-js');
< / script >
<!-- Font -->
<!-- CSS -->
< link href = '../themes/daux/css/theme-blue.min.css' rel = 'stylesheet' type = 'text/css' >
< link href = '../daux_libraries/search.css' rel = 'stylesheet' type = 'text/css' >
< / head >
< body class = "" >
< div class = "Columns content" >
< aside class = "Columns__left Collapsible" >
< button type = "button" class = "Button Collapsible__trigger" aria-controls = "sidebar_content" aria-expanded = "false" aria-label = "Toggle navigation" >
< span class = "Collapsible__trigger__bar" > < / span >
< span class = "Collapsible__trigger__bar" > < / span >
< span class = "Collapsible__trigger__bar" > < / span >
< / button >
< a class = "Brand" href = "../index.html" > RSS-Bridge< / a >
< form role = 'search' action = "/" method = "get" class = "Search" id = "search_form" >
< label for = "search_input" >
< span class = 'u-visuallyHidden' > Search< / span >
< / label >
< input
type="search"
id="search_input"
class="Search__field"
placeholder="Search..."
aria-label="Search..."
autocomplete="on"
results=25
autosave=text_search
>
< label >
< input type = "submit" class = 'u-visuallyHidden' / >
< span class = 'u-visuallyHidden' > Search...< / span >
< svg class = "Search__icon" xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 451 451" >
< path d = "M447.05 428l-109.6-109.6c29.4-33.8 47.2-77.9 47.2-126.1C384.65 86.2 298.35 0 192.35 0 86.25 0 .05 86.3.05 192.3s86.3 192.3 192.3 192.3c48.2 0 92.3-17.8 126.1-47.2L428.05 447c2.6 2.6 6.1 4 9.5 4s6.9-1.3 9.5-4c5.2-5.2 5.2-13.8 0-19zM26.95 192.3c0-91.2 74.2-165.3 165.3-165.3 91.2 0 165.3 74.2 165.3 165.3s-74.1 165.4-165.3 165.4c-91.1 0-165.3-74.2-165.3-165.4z" / >
< / svg >
< / label >
< / form >
< div class = "Collapsible__content" id = "sidebar_content" >
<!-- Navigation -->
2024-08-01 21:36:39 +00:00
< ul class = 'Nav' > < li class = 'Nav__item has-children' > < a href = "../General/Project_goals.html" class = "Nav__item__link" > < i class = "Nav__arrow" > < / i > General< / a > < ul class = 'Nav' > < li class = 'Nav__item ' > < a href = "../General/Project_goals.html" > Project-goals< / a > < / li > < li class = 'Nav__item ' > < a href = "../General/Contribute.html" > Contribute< / a > < / li > < li class = 'Nav__item ' > < a href = "../General/Requirements.html" > Requirements< / a > < / li > < li class = 'Nav__item ' > < a href = "../General/Screenshots.html" > Screenshots< / a > < / li > < li class = 'Nav__item ' > < a href = "../General/FAQ.html" > FAQ< / a > < / li > < li class = 'Nav__item ' > < a href = "../General/Public_Hosts.html" > Public Hosts< / a > < / li > < / ul > < / li > < li class = 'Nav__item ' > < a href = "../CLI/index.html" class = "Nav__item__link" > < i class = "Nav__arrow" > < / i > CLI< / a > < ul class = 'Nav' > < / ul > < / li > < li class = 'Nav__item has-children' > < a href = "../For_Hosts/index.html" class = "Nav__item__link" > < i class = "Nav__arrow" > < / i > For Hosts< / a > < ul class = 'Nav' > < li class = 'Nav__item ' > < a href = "../For_Hosts/Installation.html" > Installation< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Hosts/Updating.html" > Updating< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Hosts/Heroku_Installation.html" > Heroku Installation< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Hosts/Whitelisting.html" > Whitelisting< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Hosts/Authentication.html" > Authentication< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Hosts/Customizations.html" > Customizations< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Hosts/Custom_Configuration.html" > Custom Configuration< / a > < / li > < / ul > < / li > < li class = 'Nav__item has-children' > < a href = "../For_Developers/index.html" class = "Nav__item__link" > < i class = "Nav__arrow" > < / i > For Developers< / a > < ul class = 'Nav' > < li class = 'Nav__item ' > < a href = "../For_Developers/Coding_style_policy.html" > Coding style policy< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Developers/Pull_Request_policy.html" > Pull Request policy< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Developers/Folder_structure.html" > Folder structure< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Developers/Actions.html" > Actions< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Developers/Debug_mode.html" > Debug mode< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Developers/Github_Codespaces_Tutorial.html" > Github Codespaces Tutorial< / a > < / li > < li class = 'Nav__item ' > < a href = "../For_Developers/Development_Environment_Setup.html" > Development Environment Setup< / a > < / li > < / ul > < / li > < li class = 'Nav__item Nav__item--open has-children' > < a href = "../Bridge_API/index.html" class = "Nav__item__link" > < i class = "Nav__arrow" > < / i > Bridge API< / a > < ul class = 'Nav' > < li class = 'Nav__item ' > < a href = "../Bridge_API/How_to_create_a_new_bridge.html" > How to create a new bridge< / a > < / li > < li class = 'Nav__item ' > < a href = "../Bridge_API/BridgeAbstract.html" > BridgeAbstract< / a > < / li > < li class = 'Nav__item ' > < a href = "../Bridge_API/FeedExpander.html" > FeedExpander< / a > < / li > < li class = 'Nav__item Nav__item--active' > < a href = "../Bridge_API/WebDriverAbstract.html" > WebDriverAbstract< / a > < / li > < li class = 'Nav__item ' > < a href = "../Bridge_API/XPathAbstract.html" > XPathAbstract< / a > < / li > < / ul > < / li > < li class = 'Nav__item ' > < a href = "../Helper_functions/index.html" class = "Nav__item__link" > < i class = "Nav__arrow" > < / i > Helper functions< / a > < ul class = 'Nav' > < / ul > < / li > < li class = 'Nav__item has-children' > < a href = "../Cache_API/index.html" class = "Nav__item__link" > < i class = "Nav__arrow" > < / i > Cache API< / a > < ul class = 'Nav' > < li class = 'Nav__item ' > < a href = "../Cache_API/How_to_create_a_new_cache.html" > How to create a new cache< / a > < / li > < li class = 'Nav__item ' > < a href = "../Cache_API/CacheInterface.html" > CacheInterface< / a > < / li > < / ul > < / li > < li class = 'Nav__item ' > < a href = "../Technical_recommendations/index.html" class = "Nav__item__link" > < i class = "Nav__arrow" > < / i > Technical recommendations< / a > < ul class = 'Nav' > < / ul > < / li > < li class = 'Nav__item has-children' > < a href = "../Bridge_Specific/ActivityPub_(Mastodon).html" class = "Nav__item__link" > < i class = "Nav__arrow" > < / i > Bridge Specific< / a > < ul class = 'Nav' > < li class = 'Nav__item ' > < a href =
2024-02-10 03:42:44 +00:00
< div class = "Links" >
< hr / >
< a href = "https://github.com/RSS-Bridge/rss-bridge" target = "_blank" rel = "noopener noreferrer" > GitHub Repository< / a >
< br / >
< a href = "https://github.com/RSS-Bridge/rss-bridge/issues" target = "_blank" rel = "noopener noreferrer" > Help/Support/Bugs< / a >
< br / >
< a href = "https://github.com/RSS-Bridge/rss-bridge/pkgs/container/rss-bridge" target = "_blank" rel = "noopener noreferrer" > Docker Images< / a >
< br / >
< / div >
< div class = "CodeToggler" >
< hr / >
< label class = "Checkbox" > Show Code Blocks < input type = "checkbox" class = "CodeToggler__button--main" checked = "checked" / >
< div class = "Checkbox__indicator" > < / div >
< / label >
< / div >
< div class = "DarkModeToggler" >
< hr / >
< label class = "Checkbox" > Dark Mode < input type = "checkbox" class = "ColorMode__button" / >
< div class = "Checkbox__indicator" > < / div >
< / label >
< / div >
< div class = "PoweredBy" >
< hr / >
Powered by Daux.io < / div >
< / div >
< / aside >
< div class = "Columns__right" >
< div class = "Columns__right__content" >
< div class = "doc_content" >
< article class = "Page" >
< div class = "Page__header" >
< h1 > < a href = "../Bridge_API/index.html" > Bridge API< / a > < svg class = "Page__header--separator" xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 477.175 477.175" > < path d = "M360.73 229.075l-225.1-225.1c-5.3-5.3-13.8-5.3-19.1 0s-5.3 13.8 0 19.1l215.5 215.5-215.5 215.5c-5.3 5.3-5.3 13.8 0 19.1 2.6 2.6 6.1 4 9.5 4 3.4 0 6.9-1.3 9.5-4l225.1-225.1c5.3-5.2 5.3-13.8.1-19z" / > < / svg > < a href = "../Bridge_API/WebDriverAbstract.html" > WebDriverAbstract< / a > < / h1 >
< span class = "ModifiedDate" >
2025-01-02 12:12:42 +00:00
January 2, 2025 at 4:12 AM < / span >
2024-02-10 03:42:44 +00:00
< span class = "EditOn" >
< a href = "https://github.com/RSS-Bridge/rss-bridge/tree/master/docs/05_Bridge_API/04_WebDriverAbstract.md" target = "_blank" >
Edit on GitHub < / a >
< / span >
< / div >
< div class = "s-content" >
< p > < code > WebDriverAbstract< / code > extends < a href = "BridgeAbstract.html" > < code > BridgeAbstract< / code > < / a > and adds functionality for generating feeds
from active websites that use XMLHttpRequest (XHR) to load content and / or JavaScript to
modify content.
It highly depends on the php-webdriver library which offers Selenium WebDriver bindings for PHP.< / p >
< ul >
2025-01-02 12:12:42 +00:00
< li > < a href = "https://github.com/php-webdriver/php-webdriver" class = "Link--external" rel = "noopener noreferrer" > https://github.com/php-webdriver/php-webdriver< / a > (Project Repository)< / li >
< li > < a href = "https://php-webdriver.github.io/php-webdriver/latest/" class = "Link--external" rel = "noopener noreferrer" > https://php-webdriver.github.io/php-webdriver/latest/< / a > (API)< / li >
2024-02-10 03:42:44 +00:00
< / ul >
< p > Please note that this class is intended as a solution for websites < em > that cannot be covered
by the other classes< / em > . The WebDriver starts a browser and is therefore very resource-intensive.< / p >
< h1 > < a id = "configuration" href = "#configuration" class = "Permalink" aria-hidden = "true" title = "Permalink" > #< / a > Configuration< / h1 >
< p > You need a running WebDriver to use bridges that depend on < code > WebDriverAbstract< / code > .
The easiest way is to start the Selenium server from the project of the same name:< / p >
< pre > < code > docker run -d -p 4444:4444 --shm-size=" 2g" docker.io/selenium/standalone-chrome:latest
< / code > < / pre >
< ul >
2025-01-02 12:12:42 +00:00
< li > < a href = "https://github.com/SeleniumHQ/docker-selenium" class = "Link--external" rel = "noopener noreferrer" > https://github.com/SeleniumHQ/docker-selenium< / a > < / li >
2024-02-10 03:42:44 +00:00
< / ul >
< p > With these parameters only one browser window can be started at a time.
On a multi-user site, Selenium Grid should be used
and the number of sessions should be adjusted to the number of processor cores.< / p >
< p > Finally, the < code > config.ini.php< / code > file must be adjusted so that the WebDriver
can find the Selenium server:< / p >
< pre > < code > [webdriver]
selenium_server_url = " http://localhost:4444"
< / code > < / pre >
< h1 > < a id = "development" href = "#development" class = "Permalink" aria-hidden = "true" title = "Permalink" > #< / a > Development< / h1 >
< p > While you are programming a new bridge, it is easier to start a local WebDriver because then you can see what is happening and where the errors are. I’ ve also had good experience recording the process with a screen video to find any timing problems.< / p >
< pre > < code > chromedriver --port=4444
< / code > < / pre >
< ul >
2025-01-02 12:12:42 +00:00
< li > < a href = "https://chromedriver.chromium.org/" class = "Link--external" rel = "noopener noreferrer" > https://chromedriver.chromium.org/< / a > < / li >
2024-02-10 03:42:44 +00:00
< / ul >
< p > If you start rss-bridge from a container, then Chrome driver is only accessible
if you call it with the < code > --allowed-ips< / code > option so that it binds to all network interfaces.< / p >
< pre > < code > chromedriver --port=4444 --allowed-ips=192.168.1.42
< / code > < / pre >
< p > The < strong > most important rule< / strong > is that after an event such as loading the web page
or pressing a button, you often have to explicitly wait for the desired elements to appear.< / p >
< p > A simple example is the bridge < code > ScalableCapitalBlogBridge.php< / code > .
A more complex and relatively complete example is the bridge < code > GULPProjekteBridge.php< / code > .< / p >
< h1 > < a id = "template" href = "#template" class = "Permalink" aria-hidden = "true" title = "Permalink" > #< / a > Template< / h1 >
< p > Use this template to create your own bridge.< / p >
< pre > < code class = "language-PHP" > < ?php
class MyBridge extends WebDriverAbstract
{
const NAME = 'My Bridge';
const URI = 'https://www.example.org';
const DESCRIPTION = 'Further description';
const MAINTAINER = 'your name';
public function collectData()
{
parent::collectData();
try {
// TODO
} finally {
$this-> cleanUp();
}
}
}
< / code > < / pre >
< / div >
< nav >
< ul class = "Pager" >
< li class = Pager--prev > < a href = "../Bridge_API/FeedExpander.html" > Previous< / a > < / li > < li class = Pager--next > < a href = "../Bridge_API/XPathAbstract.html" > Next< / a > < / li > < / ul >
< / nav >
< / article >
< / div >
< / div >
< / div >
< / div >
<!-- JS -->
< script src = "../themes/daux/js/daux.min.js" > < / script >
< script >
window.searchLanguage = "";
window.searchTranslation = {"Search_one_result":"1 result","Search_results":"!count results","Search_no_results":"Nothing found","Search_common_words_ignored":"Common words are largely ignored","Search_too_short":"Search too short","Search_one_character_or_more":"Should be one character or more","Search_should_be_x_or_more":"Should be !min characters or more","Link_previous":"Previous","Link_next":"Next"};
< / script >
<!-- Search -->
< script type = "text/javascript" src = "../daux_libraries/search.min.js" > < / script >
< script >
window.search({'base_url': '../'})
< / script >
< / body >
< / html >