Package: courlan
Why coURLan?“It is important for the crawler to visit “important” pages first, so that the fraction of the Web that is visited (and kept up to date) is more meaningful.” (Cho et al. 1998)“Given that the bandwidth for conducting crawls is neither infinite nor free, it is becoming essential to crawl the Web in not only a scalable, but efficient way, if some reasonable measure of quality or freshness is to be maintained.” (Edwards et al. 2001)This library provides an additional “brain” for web crawling, scraping and document management. It facilitates web navigation through a set of filters, enhancing the quality of resulting document collections:Save bandwidth and processing time by steering clear of pages deemed low-valueIdentify specific pages based on language or text contentPinpoint pages relevant for efficient link gatheringAdditional utilities needed include URL storage, filtering, and deduplication.FeaturesSeparate the wheat from the chaff and optimize document discovery and retrieval:URL handlingValidationNormalizationSamplingHeuristics for link filteringSpam, trackers, and content-typesLanguage/Locale-aware processingWeb crawling (frontier, scheduling)Data store specifically designed for URLsUsable with Python or on the command-lineLet the coURLan fish up juicy bits for you!Here is acourlan(source:Limpkin at Harn’s Marsh by Russ, CC BY 2.0).InstallationThis package is compatible with with all common versions of Python, it is tested on Linux, macOS and Windows systems.Courlan is available on the package repositoryPyPIand can notably be installed with the Python package managerpip:$pipinstallcourlan# pip3 install on systems where both Python 2 and 3 are installed$pipinstall--upgradecourlan# to make sure you have the latest version$pipinstallgit+https://github.com/adbar/courlan.git# latest available code (see build status above)PythonMost filters revolve around thestrictandlanguagearguments.check_url()All useful operations chained incheck_url(url):>>>fromcourlanimportcheck_url# return url and domain name>>>check_url('https://github.com/adbar/courlan')('https://github.com/adbar/courlan','github.com')# filter out bogus domains>>>check_url('http://666.0.0.1/')>>># tracker removal>>>check_url('http://test.net/foo.html?utm_source=twitter#gclid=123')('http://test.net/foo.html','test.net')# use strict for further trimming>>>my_url='https://httpbin.org/redirect-to?url=http%3A%2F%2Fexample.org'>>>check_url(my_url,strict=True)('https://httpbin.org/redirect-to','httpbin.org')# check for redirects (HEAD request)>>>url,domain_name=check_url(my_url,with_redirects=True)# include navigation pages instead of discarding them>>>check_url('http://www.example.org/page/10/',with_nav=True)# remove trailing slash>>>check_url('https://github.com/adbar/courlan/',trailing_slash=False)Language-aware heuristics, notably internationalization in URLs, are available inlang_filter(url, language):# optional language argument>>>url='https://www.un.org/en/about-us'# success: returns clean URL and domain name>>>check_url(url,language='en')('https://www.un.org/en/about-us','un.org')# failure: doesn't return anything>>>check_url(url,language='de')>>># optional argument: strict>>>url='https://en.wikipedia.org/'>>>check_url(url,language='de',strict=False)('https://en.wikipedia.org','wikipedia.org')>>>check_url(url,language='de',strict=True)>>>Define stricter restrictions on the expected content type withstrict=True. Also blocks certain platforms and pages types crawlers should stay away from if they don’t target them explicitly and other black holes where machines get lost.# strict filtering: blocked as it is a major platform>>>check_url('https://www.twitch.com/',strict=True)>>>Sampling by domain name>>>fromcourlanimportsample_urls>>>my_urls=['https://example.org/'+str(x)forxinrange(100)]>>>my_sample=sample_urls(my_urls,10)# optional: exclude_min=None, exclude_max=None, strict=False, verbose=FalseWeb crawling and URL handlingDetermine if a link leads to another host:>>>fromcourlanimportis_external>>>is_external('https://github.com/','https://www.microsoft.com/')True# default>>>is_external('https://google.com/','https://www.google.co.uk/',ignore_suffix=True)False# taking suffixes into account>>>is_external('https://google.com/','https://www.google.co.uk/',ignore_suffix=False)TrueOther useful functions dedicated to URL handling:extract_domain(url, fast=True): find domain and subdomain or just domain withfast=Falseget_base_url(url): strip the URL of some of its partsget_host_and_path(url): decompose URLs in two parts: protocol + host/domain and pathget_hostinfo(url): extract domain and host info (protocol + host/domain)fix_relative_urls(baseurl, url): prepend necessary information to relative links>>>fromcourlanimport*>>>url='https://www.un.org/en/about-us'>>>get_base_url(url)'https://www.un.org'>>>get_host_and_path(url)('https://www.un.org','/en/about-us')>>>get_hostinfo(url)('un.org','https://www.un.org')>>>fix_relative_urls('https://www.un.org','en/about-us')'https://www.un.org/en/about-us'Other filters dedicated to crawl frontier management:is_not_crawlable(url): check for deep web or pages generally not usable in a crawling contextis_navigation_page(url): check for navigation and overview pages>>>fromcourlanimportis_navigation_page,is_not_crawlable>>>is_navigation_page('https://www.randomblog.net/category/myposts')True>>>is_not_crawlable('https://www.randomblog.net/login')TruePython helpersHelper function, scrub and normalize:>>>fromcourlanimportclean_url>>>clean_url('HTTPS://WWW.DWDS.DE:80/')'https://www.dwds.de'Basic scrubbing only:>>>fromcourlanimportscrub_urlBasic canonicalization/normalization only, i.e. modifying and standardizing URLs in a consistent manner:>>>fromurllib.parseimporturlparse>>>fromcourlanimportnormalize_url>>>my_url=normalize_url(urlparse(my_url))# passing URL strings directly also works>>>my_url=normalize_url(my_url)# remove unnecessary components and re-order query elements>>>normalize_url('http://test.net/foo.html?utm_source=twitter&post=abc&page=2#fragment',strict=True)'http://test.net/foo.html?page=2&post=abc'Basic URL validation only:>>>fromcourlanimportvalidate_url>>>validate_url('http://1234')(False,None)>>>validate_url('http://www.example.org/')(True,ParseResult(scheme='http',netloc='www.example.org',path='/',params='',query='',fragment=''))TroubleshootingCourlan uses an internal cache to speed up URL parsing. It can be reset as follows:>>>fromcourlan.metaimportclear_caches>>>clear_caches()UrlStore classTheUrlStoreclass allow for storing and retrieving domain-classified URLs, where a URL likehttps://example.org/path/testpageis stored as the path/path/testpagewithin the domainhttps://example.org. It features the following methods:URL managementadd_urls(urls=[],appendleft=None, visited=False): Add a list of URLs to the (possibly) existing one. Optional: append certain URLs to the left, specify if the URLs have already been visited.add_from_html(htmlstring, url, external=False, lang=None, with_nav=True): Extract and filter links in a HTML string.discard(domains): Declare domains void and prune the store.dump_urls(): Return a list of all known URLs.print_urls(): Print all URLs in store (URL + TAB + visited or not).print_unvisited_urls(): Print all unvisited URLs in store.get_all_counts(): Return all download counts for the hosts in store.get_known_domains(): Return all known domains as a list.get_unvisited_domains(): Find all domains for which there are unvisited URLs.total_url_number(): Find number of all URLs in store.is_known(url): Check if the given URL has already been stored.has_been_visited(url): Check if the given URL has already been visited.filter_unknown_urls(urls): Take a list of URLs and return the currently unknown ones.filter_unvisited_urls(urls): Take a list of URLs and return the currently unvisited ones.find_known_urls(domain): Get all already known URLs for the given domain (ex. “https://example.org”).find_unvisited_urls(domain): Get all unvisited URLs for the given domain.get_unvisited_domains(): Return all domains which have not been all visited.reset(): Re-initialize the URL store.Crawling and downloadsget_url(domain): Retrieve a single URL and consider it to be visited (with corresponding timestamp).get_rules(domain): Return the stored crawling rules for the given website.store_rules(website, rules=None): Store crawling rules for a given website.get_crawl_delay(): Return the delay as extracted from robots.txt, or a given default.get_download_urls(timelimit=10): Get a list of immediately downloadable URLs according to the given time limit per domain.establish_download_schedule(max_urls=100, time_limit=10): Get up to the specified number of URLs along with a suitable backoff schedule (in seconds).download_threshold_reached(threshold): Find out if the download limit (in seconds) has been reached for one of the websites in store.unvisited_websites_number(): Return the number of websites for which there are still URLs to visit.is_exhausted_domain(domain): Tell if all known URLs for the website have been visited.Persistancewrite(filename): Save the store to disk.load_store(filename): Read a UrlStore from disk (separate function, not class method).Optional settings:
-compressed=True: activate compression of URLs and rules
-language=XX: focus on a particular target language (two-letter code)
-strict=True: stricter URL filtering
-verbose=True: dump URLs if interrupted (requires use ofsignal)Command-lineThe main fonctions are also available through a command-line utility.$courlan--inputfileurl-list.txt--outputfilecleaned-urls.txt$courlan--helpusage:courlan[-h]-iINPUTFILE-oOUTPUTFILE[-dDISCARDEDFILE][-v][-pPARALLEL][--strict][-lLANGUAGE][-r][--sampleSAMPLE][--exclude-maxEXCLUDE_MAX][--exclude-minEXCLUDE_MIN]optional arguments:-h,--helpshow this help message and exitI/O:Manage input and output-iINPUTFILE,--inputfileINPUTFILEname of input file (required)-oOUTPUTFILE,--outputfileOUTPUTFILEname of output file (required)-dDISCARDEDFILE,--discardedfileDISCARDEDFILEname of file to store discarded URLs (optional)-v,--verboseincrease output verbosity-pPARALLEL,--parallelPARALLELnumber of parallel processes (not used for sampling)Filtering:Configure URL filters--strictperform more restrictive tests-lLANGUAGE,--languageLANGUAGEuse language filter (ISO 639-1 code)-r,--redirectscheck redirectsSampling:Use sampling by host, configure sample size--sampleSAMPLEsize of sample per domain--exclude-maxEXCLUDE_MAXexclude domains with more than n URLs--exclude-minEXCLUDE_MINexclude domains with less than n URLsLicensecoURLanis distributed under theApache 2.0 license.Versions prior to v1 were under GPLv3+ license.Settingscourlanis optimized for English and German but its generic approach is also usable in other contexts.Details of strict URL filtering can be reviewed and changed in the filesettings.py. To override the default settings,clone the repositoryandre-install the package locally.ContributingContributionsare welcome!Feel free to file issues on thededicated page.AuthorThis effort is part of methods to derive information from web documents in order to buildtext databases for research(chiefly linguistic analysis and natural language processing). Extracting and pre-processing web texts to the exacting standards of scientific research presents a substantial challenge for those who conduct such research. Web corpus construction involves numerous design decisions, and this software package can help facilitate text data collection and enhance corpus quality.Barbaresi, A. “Trafilatura: A Web Scraping Library and Command-Line Tool for Text Discovery and Extraction.”Proceedings of ACL/IJCNLP 2021: System Demonstrations, 2021, pp. 122-131.Barbaresi, A. “Generic Web Content Extraction with Open-Source Software.”Proceedings of the 15th Conference on Natural Language Processing (KONVENS 2019), 2019, pp. 267-268.Contact: seehomepageorGitHub.Software ecosystem: seethis graphic.Similar workThese Python libraries perform similar handling and normalization tasks but do not entail language or content filters. They also do not primarily focus on crawl optimization:furluralyarlReferencesCho, J., Garcia-Molina, H., & Page, L. (1998). Efficient crawling through URL ordering.Computer networks and ISDN systems, 30(1-7), 161–172.Edwards, J., McCurley, K. S., and Tomlin, J. A. (2001). “An adaptive model for optimizing performance of an incremental web crawler”. InProceedings of the 10th international conference on World Wide Web - WWW ‘01, pp. 106–113.