Here's the whole workflow, start to finish. Each piece is broken down and explained below.
using System
using System
using GenerallyPositive;
using GenerallyPositive
using static GenerallyPositive
GPAL
IGPALGrid<string> retGrid = GPAL
Selector nextPageButton = "//a[contains(@class, 'pagination__next icon-link')]";
nextPageButton
Selector resultCard = "//li[starts-with(@id, 'item')]";
resultCard
Selector imageColumn = "
imageColumn
Selector descriptionColumn = "
descriptionColumn
Selector linkColumn = "
linkColumn
Selector priceColumn = "
priceColumn
Selector searchButton = "#gh-search-btn";
searchButton
Selector inputSearchSelector = "#gh-ac";
inputSearchSelector
IBrowser browser = GPAL
browser
CallIfStatus CallIfFound(IBrowser browser, List<IGPALElement> foundElements, List<IGPALElement> matchedElements, Selector selector, bool matchedAll)
{
foreach (IGPALElement webElement in foundElements)
Debug
return CallIfStatus
}
CallIfStatus CallIfNotFound(IBrowser browser, List<IGPALElement> foundElements, List<IGPALElement> matchedElements, Selector selector, bool matchedAll)
{
Debug
return CallIfStatus
}
Every workflow starts with a few global settings - here we turn on console logging, auto-update the web driver, and add a human-like typing delay. Then we define each Selector once, give it a friendly name, and (for the search button) require its text to match "Search". Selectors are just values - define them once, reuse them anywhere in the workflow.
GPAL
Selector searchButton = "#gh-search-btn";
searchButton
Selector inputSearchSelector = "#gh-ac";
inputSearchSelector
WithSelectorName isn't just cosmetic - it's the name GPAL uses when it logs information and exception events for that selector, which makes troubleshooting much easier. See Selectors and Selector Matching for the full picture.
GPAL.Browser is a fluent factory: pick a browser type, pick an automation engine, tell it to wait until the page is ready, and go to a URL. ToGPALObject() returns the live IBrowser you'll drive for the rest of the workflow.
IBrowser browser = GPAL
Swapping AutomationEngine.PuppeteerPort for Selenium, OttoMagic, or any of the other 8 engines doesn't change anything below this line. See Automation Engines.
This is the heart of GPAL. InElement(resultCard) makes every result card a root, so the column selectors after it (relative .// XPaths) are searched inside each card. Each card gives one cell per column, so a card with two prices does not shift the rows below. WithSelector adds elements to the current unit of work - here, the description, price, link, and image columns for up to 10 results per page. WithAllThatMatch tells GPAL how many matching elements to use. No loops: GPAL applies each action across every matched element for you.
browser
CallIfFound and CallIfNotFound let you react to whether a selector matched anything - here we just log element info, or the name of the selector that found nothing. WithNextPageButton plus WithPages handles pagination automatically. GetGrid pulls everything into an in-memory grid, and SaveTo writes it straight to a file.
Passing true kills the running web driver process. Use true when the workflow is completely done; use false if another workflow in the same run still needs that driver.
Showing off some plain text in these paragraphs eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Here you can find different accents and emphasis sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
This is a link and how it could look like bestlinkinthebeautifulworld. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Here's just some classic bold text adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam notBoldSecondbestlinkinthebeautifulworld illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at adipisicing elit libero vel voluptas? Expedita, adipisicing facere dolores voluptatem ad ab rem assumenda soluta!
Other cuple of colors in case we want to emphasize several ways adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at voluptatem libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Repudiandae quas consequuntur illo numquam assumenda autem exercitationem distinctio perspiciatis in natus. Eius dicta similique ipsam ipsa minima, nemo quae enim tempore.
GPAL
.CallIfNotFound(GenericCallIfNotFound)
.WithPublishToConsole();
//System.Drawing.Rectangle windowSize = new System.Drawing.Rectangle(10, 10, 1500, 1024);
// NOTE: we have to set browser = before we execute any steps
// this is due to the 'GenericCallIfNotFound' which might throw an exception, and BankScraper will not have the browser set when it calls scraper.Close()
// until the complete fluent line gets executed (meaning every step, meaning browser is not set until everything else succeeds)
browser = GPAL.Browser
.WithBrowserType(Enums.BrowserType.Chrome)
.WithProfileDataDirectory(ChromeProfileLocation)
.WithUseAutomationEngine(AutomationEngine.Selenium)
.WithWindowSize(new System.Drawing.Rectangle(0,0,1920,1080))
.ToGPALObject();