From 52f68fa2b2280001835926f6716e3ae9c1784bf4 Mon Sep 17 00:00:00 2001 From: Laurie Burchell Date: Thu, 5 Jun 2025 17:51:24 +0100 Subject: [PATCH 1/4] docs: reformat into tasks, clarify and prettify --- .gitignore | 1 + README_LVB.md | 358 +++++++++++++++++++++++++++++++++++++ img/crawl_dropdown.png | Bin 0 -> 44488 bytes img/crawl_file_listing.png | Bin 0 -> 103555 bytes 4 files changed, 359 insertions(+) create mode 100644 README_LVB.md create mode 100644 img/crawl_dropdown.png create mode 100644 img/crawl_file_listing.png diff --git a/.gitignore b/.gitignore index 89c5078..1075339 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ whirlwind.parquet collinfo.json .venv/ .vscode/ +.idea/ diff --git a/README_LVB.md b/README_LVB.md new file mode 100644 index 0000000..a145863 --- /dev/null +++ b/README_LVB.md @@ -0,0 +1,358 @@ +# Whirlwind Tour of Common Crawl's Datasets using Python + +TBD: (overview of common crawls datasets and what they can be used for) + +(tour is to get to know file formats, meet some of the Python tools for interacting with them, and to learn different ways to access the crawls) + +The goal of this whirlwind tour is to show you how a single webpage appears in all of these different places. That webpage is [https://an.wikipedia.org/wiki/Escopete](https://an.wikipedia.org/wiki/Escopete), which we crawled on the date 2024-05-18T01:58:10Z. + +TBD: check this all applies at the end + +In the Whirlwind Tour, we will: +1) explore the WARC, WET and WAT file formats used to store Common Crawl's data. +2) play with some useful Python packages for interacting with the data: [warcio](https://github.com/webrecorder/warcio), [cdxj-indexer](https://github.com/webrecorder/cdxj-indexer), +[cdx_toolkit](https://github.com/cocrawler/cdx_toolkit), +and [duckdb](https://duckdb.org/). +3) learn about how the data is compressed to allow random access. +4) use the CDXJ index and the columnar index to access the data we want. + +**Prerequisites:** To get the most out of this tour, you should be comfortable with Python3, running commands on the command line, and basic SQL. Some knowledge of HTTP requests and HTML is also helpful but not essential. We assume you have `make` and `virtualenv` installed. + +We use a [Makefile](https://makefiletutorial.com) to provide many of the commands needed to run this tutorial. To see what commands are being run, open the `Makefile` and find the relevant target: e.g. `make install` runs `pip install -r requirements.txt`. + +## Task 0: Set-up + +This tutorial was written on Linux and MacOS. We think it should also work on Windows WSL, but raise an issue if you encounter problems. + +### Clone the repository and create a local Python environment + +First, [clone this repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) to create a local copy, then navigate to the `whirlwind-python` directory on your computer. + +In general, it's a good idea to set up separate virtual environments (venvs) for Python projects. This lets you install packages without changing either the system Python environment or any of your other Python projects. + +If you already have your own favorite venv scheme, you can skip this step (we used the [Pycharm IDE](https://www.jetbrains.com/pycharm) to manage environment creation). Otherwise, you can create a venv on the command line by running: + +```make venv``` + +After you create this venv, you'll need to activate it: + +```source ~/venv/whirlwind/bin/activate``` + +On many systems, you will now see the name of the venv in parentheses before the command prompt. You'll need to activate the environment again if you log out and log in again. + +Next, let's install the necessary software for this tour: + +```make install``` + +This command will print out a screen-full of output and install the Python packages in `requirements.txt` to your venv. + +### Install and configure AWS-CLI + +We will use the AWS Command Line Interface (CLI) later in the tour to access the data stored in Common Crawl's S3 bucket. Instructions on how to install the AWS-CLI and configure your account are available on the [AWS website](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). + +## Task 1: Look at the crawl data + +Common Crawl's website includes a [Get Started](https://commoncrawl.org/get-started) guide which summarises different ways to access the data and the file formats. We can use the dropdown menu to access the links for downloading crawls over HTTP(S): + +![crawl_dropdown.png](img/crawl_dropdown.png) + +If we click on `CC-MAIN-2024-22' in the dropdown, we are taken to a page listing the files contained in this crawl: + +![crawl_file_listing.png](img/crawl_file_listing.png) + +In this whirlwind tour, we're going to look first at the WARC, WET, and WAT files: the data types which store the crawl data. Later, we will look at the two index files and how these help us access the crawl data we want. + +### WARC + +[WARC files](https://iipc.github.io/warc-specifications/specifications/warc-format/warc-1.0/) are a container that holds files, similar to zip and tar files. We use this data format to store raw crawl data. As you can see in the file listing above, it is very large even when compressed! Luckily, we have a much smaller example to look at. + +Open `whirlwind.warc` in your favorite text editor. Note that this is an uncompressed version of the file; normally we always work with these files while they are compressed. This is the WARC corresponding to the single webpage we mentioned in the introduction. + +You'll see four records total, with the start of each record marked with the header `WARC/1.0` followed by metadata related to that particular record. The `WARC-Type` field tells you the type of each record. In our WARC file, we have: +1) a `warcinfo` record. Every WARC has that at the start. +2) the `request` to the webserver, with its HTTP headers. +3) the `response` from the webserver, with its HTTP headers followed by the html. +4) a `metadata` record related to the HTTP response. + +### WET + +WET (WARC Encapsulated Text) files only contain the body text of web pages extracted from the HTML and exclude any HTML code, images, or other media. This makes them useful for text analysis and natural language processing (NLP) tasks. + +Open `whirlwind.warc.wet`: this is the WET derived from our original WARC. We can see that it's still in WARC format with two records: +1) a `warcinfo` record. +2) a `conversion` record: the HTTP headers have been removed leaving only the extracted text. + +### WAT + +WAT (Web ARChive Timestamp) files contain metadata associated with the crawled web pages (e.g. parsed data from the HTTP response headers, links extracted from HTML pages, server response codes etc.). They are useful for analysis that requires understanding the structure of the web. + +Open `whirlwind.warc.wat`: this is the WAT derived from our original WARC. Like the WET file, it's also in WARC format. This file contains a metadata record for each response in the WARC. The metadata is stored as json. You might want to feed this json into a pretty-printer to read it more easily. For example, you can save just the json into a file and use `python -m json.tool FILENAME` to pretty-print it. + +Now that we've looked at the uncompressed versions of these files to understand their structure, the rest of the tour will focus on the usual software tools used to manipulate the compressed versions of these files. + +## Task 2: Iterate over WARC, WET, and WAT files + +The [warcio](https://github.com/webrecorder/warcio) Python library lets us read and write WARC files programmatically. + +Let's use it to iterate over our WARC, WET, and WAT files and print out the record types we looked at before. First, look at the code in `warcio-iterator.py`: + +
+ Click to view code + +```python +'''Generic example iterator, similar to what's in the warcio README.''' + +import sys + +from warcio.archiveiterator import ArchiveIterator + +for file in sys.argv[1:]: + with open(file, 'rb') as stream: + for record in ArchiveIterator(stream): + print(' ', 'WARC-Type:', record.rec_type) + if record.rec_type in {'request', 'response', 'conversion', 'metadata'}: + print(' ', 'WARC-Target-URI', record.rec_headers.get_header('WARC-Target-URI')) +``` +
+ +The `ArchiveIterator` reads the WARC content in a single pass and allows us to access the attributes of each record (e.g. the record type through `record.rec_type`). + +Now run: + +`make iterate` + +This will run `warcio-iterator.py` on `whirlwind.warc.gz`, `whirlwind.warc.wet.gz`, and `whirlwind.warc.wat.gz` in turn. You should see output like the following: + +
+ Click to view output + +``` +iterating over all of the local warcs: + +warc: +python ./warcio-iterator.py whirlwind.warc.gz + WARC-Type: warcinfo + WARC-Type: request + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: response + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: metadata + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + +wet: +python ./warcio-iterator.py whirlwind.warc.wet.gz + WARC-Type: warcinfo + WARC-Type: conversion + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + +wat: +python ./warcio-iterator.py whirlwind.warc.wat.gz + WARC-Type: warcinfo + WARC-Type: metadata + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete +``` +
+ +The output has three sections, one each for the WARC, WET, and WAT. For each one, it prints the record types we saw before, plus the `WARC-Target-URI` for those record types that have it. + +## Task 3: Index the WARC, WET, and WAT + +The example WARC files we've been using are tiny and easy to work with. The real WARC files are around a gigabyte in size and contain about 30,000 webpages each. What's more, we have around 24 million of these files! To read all of them, we could iterate, but what if we wanted random access so we could read just one particular record? We do that with an index. + +We have two versions of the index: the CDX index and the columnar index. The CDX index is useful for looking up single pages, whereas the columnar index is better suited to analytical and bulk queries. We'll look at both in this tour, starting with the CDX index. + +### CDX(J) index + +The CDX index files are sorted plain-text files, with each line containing information about a single capture in the WARC. Technically, Common Crawl uses CDXJ index files since the information about each capture is formatted as JSON. + +We can create our own CDXJ index from the local WARCs by running: + +```make cdxj``` + +This uses the [cdxj-indexer](https://github.com/webrecorder/cdxj-indexer) library to generate CDXJ index files for our WARC files by running the code below: + +
+ Click to view code + +``` +creating *.cdxj index files from the local warcs +cdxj-indexer whirlwind.warc.gz > whirlwind.warc.cdxj +cdxj-indexer --records conversion whirlwind.warc.wet.gz > whirlwind.warc.wet.cdxj +cdxj-indexer whirlwind.warc.wat.gz > whirlwind.warc.wat.cdxj +``` + +
+ +Now look at the `.cdxj` files with `cat whirlwind*.cdxj`. You'll see +that each file has one entry in the index. The WARC only has the response record indexed, since by default cdxj-indexer guesses that you won't ever want to random-access the request or metadata. WET and WAT have the conversion and metadata records indexed. + +(Note: CCF doesn't publish a WET or WAT index, just WARC.) + +For each of these records, there's one text line in the index - yes, it's a flat file! It starts with a string like `org,wikipedia,an)/wiki/escopete 20240518015810`, followed by a JSON blob. + +The starting string is the primary key of the index. The first thing is a [SURT](http://crawler.archive.org/articles/user_manual/glossary.html#surt) (Sort-friendly URI Reordering Transform). The big integer is a date, in ISO-8601 format with the delimiters removed. + +What is the purpose of this funky format? It's done this way because these flat files (300 gigabytes total per crawl) can be sorted on the primary key using any out-of-core sort utility e.g. the standard Linux `sort`, or one of the Hadoop-based out-of-core sort functions. + +The JSON blob has enough information to extract individual records: it says which warc file the record is in, and the offset and length of +the record. We'll use that in the next section. + +## Task 4: Use the CDXJ index to extract raw content from the local WARC, WET, and WAT + +Normally, compressed files aren't random access. However, the WARC files use a trick to make this possible, which is that every record needs to be separately compressed.The `gzip`compression utility supports this, but it's rarely used. + +To extract one record from a warc file, all you need to know is the filename and the offset into the file. If you're reading over the web, then it really helps to know the exact length of the record. + +Run: + +```make extract``` + +to run a set of extractions from your local +`whirlwind.*.gz` files with `warcio` using the code below: + +
+ Click to view code + +``` +creating extraction.* from local warcs, the offset numbers are from the cdxj index +warcio extract --payload whirlwind.warc.gz 1023 > extraction.html +warcio extract --payload whirlwind.warc.wet.gz 466 > extraction.txt +warcio extract --payload whirlwind.warc.wat.gz 443 > extraction.json +hint: python -m json.tool extraction.json +``` + +
+ +The offset numbers in the Makefile are the same +ones as in the index. Look at the three output files: `extraction.html`, `extraction.txt`, and `extraction.json` (pretty-print the json with `python -m json.tool extraction.json`). + +Notice that we extracted HTML from the WARC, text from WET, and JSON from the WAT (as shown in the different file extensions). This is because the payload in each file type is formatted differently! + +## Task 5: Wreck the WARC by compressing it wrong + +As mentioned earlier, WARC/WET/WAT files look like they're gzipped, but they're actually gzipped in a particular way that allows random access. This means that you can't `gunzip` and then `gzip` a warc without wrecking random access. This example: + +* creates a copy of one of the warc files in the repo +* uncompresses it +* recompresses it the wrong way +* runs `warcio-iterator` over it to show that it triggers an error +* recompresses it the right way using `warcio recompress` +* shows that this compressed file works + +Run + +```make wreck_the_warc``` + +and read through the output. You should get something like the code below: + +
+ Click to view code + +``` +we will break and then fix this warc +cp whirlwind.warc.gz testing.warc.gz +rm -f testing.warc +gunzip testing.warc.gz + +iterate over this uncompressed warc: works +python ./warcio-iterator.py testing.warc + WARC-Type: warcinfo + WARC-Type: request + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: response + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: metadata + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + +compress it the wrong way +gzip testing.warc + +iterating over this compressed warc fails +python ./warcio-iterator.py testing.warc.gz || /usr/bin/true + WARC-Type: warcinfo +Traceback (most recent call last): + File "/home/ccgreg/github/whirlwind-python/./warcio-iterator.py", line 9, in + for record in ArchiveIterator(stream): + File "/home/ccgreg/venv/whirlwind/lib/python3.10/site-packages/warcio/archiveiterator.py", line 112, in _iterate_records + self._raise_invalid_gzip_err() + File "/home/ccgreg/venv/whirlwind/lib/python3.10/site-packages/warcio/archiveiterator.py", line 153, in _raise_invalid_gzip_err + raise ArchiveLoadFailed(msg) +warcio.exceptions.ArchiveLoadFailed: + ERROR: non-chunked gzip file detected, gzip block continues + beyond single record. + + This file is probably not a multi-member gzip but a single gzip file. + + To allow seek, a gzipped WARC must have each record compressed into + a single gzip member and concatenated together. + + This file is likely still valid and can be fixed by running: + + warcio recompress + + +now let's do it the right way +gunzip testing.warc.gz +warcio recompress testing.warc testing.warc.gz +4 records read and recompressed to file: testing.warc.gz +No Errors Found! + +and now iterating works +python ./warcio-iterator.py testing.warc.gz + WARC-Type: warcinfo + WARC-Type: request + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: response + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: metadata + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete +``` + +
+ +## Task 6: Use cdx_toolkit to query the full cdx index and download those captures from AWS S3 + +Some of our users only want to download a small subset of the crawl. They want to run queries against an index, either the CDX index we just talked about, or in the columnar index, which we'll talk about later. + +The [cdx_toolkit](https://github.com/cocrawler/cdx_toolkit) is a set of tools for working with CDX indices of web crawls and archives. It knows how to query the CDX index across all of our crawls and also can create WARCs of just the records you want. We will fetch the same record from Wikipedia that we've been using for the whirlwind tour. + +Run + +```make cdx_toolkit``` + +The output looks like this: + +
+ Click to view output + +``` +look up this capture in the comoncrawl cdx index +cdxt --cc --from 20240518015810 --to 20240518015810 iter an.wikipedia.org/wiki/Escopete +status 200, timestamp 20240518015810, url https://an.wikipedia.org/wiki/Escopete + +extract the content from the commoncrawl s3 bucket +rm -f TEST-000000.extracted.warc.gz +cdxt --cc --from 20240518015810 --to 20240518015810 warc an.wikipedia.org/wiki/Escopete + +index this new warc +cdxj-indexer TEST-000000.extracted.warc.gz > TEST-000000.extracted.warc.cdxj +cat TEST-000000.extracted.warc.cdxj +org,wikipedia,an)/wiki/escopete 20240518015810 {"url": "https://an.wikipedia.org/wiki/Escopete", "mime": "text/html", "status": "200", "digest": "sha1:RY7PLBUFQNI2FFV5FTUQK72W6SNPXLQU", "length": "17455", "offset": "379", "filename": "TEST-000000.extracted.warc.gz"} + +iterate this new warc +python ./warcio-iterator.py TEST-000000.extracted.warc.gz + WARC-Type: warcinfo + WARC-Type: response + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete +``` + +
+ +We look up the capture using the `cdxt` commands by specifying the exact URL (`an.wikipedia.org/wiki/Escopete`) and the date of its capture (20240518015810). The output is the WARC file `TEST-000000.extracted.warc.gz` which contains a `warcinfo` record explaining what the WARC is, followed by the `response` record we requested. The Makefile target then runs `cdxj-indexer` on this new WARC to make a CDXJ index of it as in Task 3, and finally iterates over the WARC using `warcio-iterator.py` as in Task 2. + +If you dig into `cdx_toolkit`'s code, you'll find that it is using the offset and length of the WARC record, as returned by the CDX index query, to make a HTTP byte range request to S3 to download the single WARC record we want. It only downloads the response WARC record because our CDX index only has the response records indexed. + +## Task 7: + + + diff --git a/img/crawl_dropdown.png b/img/crawl_dropdown.png new file mode 100644 index 0000000000000000000000000000000000000000..64b9bb0aff2c1b6e6567f9b967315966aaa9a680 GIT binary patch literal 44488 zcmc$_^493Q`IJA~PU4Gz=+7NSA=b zz)(Yf$LD$9bIw0-&iQRVd(X_?d#!b^`?{`m?L;F3ElRQnWH>lDlsek#&v0GRAWUMa! znktV0U(tb-3h6GjaE8VRJ6A(N!z!-BfmB?618BDT}r%AasZS_vt#Q29+oHrW@n^ zA(oL;`0I~!O~b-OcIN;7d*6ddZz@mkUv2+A&GZTkypeuQ6z29XFW4No67^uZRBgC{jkQ-#J%H+i$kVLRmCJ_rh5kTMnrH zdhOnPzgw;N2|QPdYri;)?+KV$3ZmZk9oP9D*3CP!)aT<~8?dXG=NQxzWEE z=*}c1>pG8KYhb*mtBsRl9!vxE8!@ zT~@JZeoMKh^WFW5>hd=J_0;Z7``WUN^Db<^De-%L!=H)xl7sZivx@wNEY4nc-!0)! zqL<;isMFh&KEuMN{{H?=q$7D!xtE}89`G!jeI&mDr{hIREcMk=>5P_S(16kJ`cfR3 zBlF;3!qj_GIZLSH`;-?uOhe1xq>floSIB{hwFY-n?sq#g`0?XCI+K9qW5h^d7|a zUm@;T=(s%cZ#sVcWA|f)^Tzg(pT#k9XIB-t_NLyll#Y}zR>SYQN_ZO;%B~Tto3lD& zYH2BG*zaX$*Rpd)>~hy_@KFo8{j>raN?H_j8G8Z@S4c>cy)EpSBZBFeyctiduu{2` z$8gJ6^lpAn$D9)!oqrnCxkDn6j&gUiTh8)3DdZY2nFj8{uB(`;N=lx2bnBph$%GEd zkF|XemU5j-yY(L!^gE>tt&40B`*zrI_ZcZ91@J zNp1npJ(??o(zC*sPV4A#C1MY~_f9=fLqWcJKkolGv@Z9dsl!BVmpZ6uWV}Zf;W57m6I0j zglfG@T!^b}zPlAA9*`hN)2GqemPx)WYG4BWErMTcG}M0Lul)Qu=j!ghec zL-R4y1T+Ac!p5j|>;?wjB?VlKDQ%XK!NGF28T52F?GN-AIFHbd6w1s9okelwA)o=v zN2t$P@7l4z0|}2zddl;_5KZeP6+t0^5-x1(5OMysbSy`nRcaug{&(2_*oXO$p?^5D!uJaQ?e}X+KR~?lC3|Qr2H~dZ3vPMM{r&iX#0SMpf!{0 zV@R$|Ip4N(!o!!5celH$C)oUtf0lCHbO{Vg!rTA6d+a8jwMipS&D)$p?9?%}n-Yf$s*dAMB0Qpnbm>!-yZgD+0u zJJ_{#!PHoKtZoIGUMp8%d$+9MM4BdF^(dRvhMm@KV>+#<(sGP?JN-^p{fwMku)P(L z8#arn9tr=Sy7*XKS(*2h$<-r6#VciuzwqaGN=h%KIi_4Gd5DpTiD2f86dKSqdz5wL z8Y~Ii=wJQrRqx*s$pv^(V_@9^m01=9uk6yGV4OE#yLD+nK)d^4QEyZOcpj zA@})ZUb+r03)#f90l;u^HtS}jzUpf5;x;Ad@m#un zfn-J2n6r*eGH$>BNIu+XDSCVr_DSXMkpVm8r^y;8OL zp`Q?!c5dnPVAdLZ%=%yOAoQu`WlOO&fY=N~ZF#SNAN@1r0*9FC(t%~odedc&g9htY z0CSwexxHrs!i@(eD||#O_J~eH;=0+OqhH17#Athix4fRbJzvN!E-ZT?&GHX1A&LI(ydAY%TPZjba1f)91ZwiL+79G^LH^cwPSt9K>Wo@M0fn#ah(DQwGn+ZbO&h4wZgaV%UMv^q9QaU-CN{9QkA@M3Ogl1s2r6>%d7$^?Y_+G#kIn zI4EQCP1cs9>-6}B*10w?JpFe6T*&Uy);vOgr$qjTFr7ts| z%RDO!fzFrIv^te8Hp2N1N`pQlzo5%>u1`qF@AqTSvGk-8TLT@nKW+`=_Y0@d<^8Lr zeLrdY3pHxVI1qiJ{cE8>%+JjKfYdKQEJlh zTsM%;dGILhGqoaGk~DXuE5dWyetq`>WKqmswo$=_*~15>A_ga$zxJdP_&ojt*Ffv% zfu`Evm|S+PsUjWo_Mag?BFCs${OwHSzr17)PQ6Ra-?}u?RyK zWLFMNHjVEJo5?rNLA;TkuQvFU7W#6T4HPP}D|c-#9QxAv|0vGX$qU5qs5QK z%Kt_D&2UXY0E=b2T{h_Tc-?BpL}nTC$d%)s^ia#u7ps|z3po?zqS1DrlGU;3{@awtZd&Hd_(75$B1nF}$~JIg5g zG6&G0f2~GI572r3?)$de`u~0-qrJs zL-JnSaC&lKz`^#(m~7DUN>y6^kD1F=tSWc&!%&^{1zFHrKEzg@7kQN zM=tdx9jEdB-Yt4v-saXzx?Cz+WWYI<7@7Y=cC|_WjAeMGv2psG;y@ZIMl7_0kuN4e z#!H{2n8n+!EVv;Va5n~hXiMH7p;u2EwnRVPU+btCd+8vyoxhLo;Y32*CoW`eU|v^P z#NY-;&=9d`y+-(a8_*k_;WQhwYD#%CLMInGYWJQOWLr-&&6ya(gES+T`j!Cm5dH8C zO(q~LNUfn$mHP}!ys?D6oj=$l%kqYQlEX)O%Y%_r_eC}0z_69DX1p5`@*FxwAwIJY>ru^ky4*CfYg-Sc|3``N6YC)ABt~a+U%bGjC(YZM_|AzNNWll7Xpxr9 zo5V$?&{Ydk)uqWIeo)L2u0wUlnOK|BIds0RM}z5z&9&6sR3o}@e1ilaALz)~AQ8;# zX{3;c0&9lfeCSAXcOsVWQ^aW!h{WtfI6k0g;Xha)v2CA5Flur)!JTvy2o`W&`>IDB z`{B#K7cpmwp1=2iMmDJ7Kf#+ZQUTs{-cV4|?ZNA8<-8+LdkClP2b5;{aQ-00>NIFc zN0py(uP|9-LYr$i0aNajME)xAgvdnlYCfyFg;$YbQwmKVqzK0QX>1Fb$tV{)E{U$h zt?FI@y*ge+DEHtN2mn~7_E`hEsawqn54ktOQ?C9AUt1MH*6=he(UA@)7 zvmX;*8s=)WTukKTYW+wOKAIxZZFfX_a%uLBsi4j!A# zukk3AmQj8R1>g9tDQwxmZ2I*}cToqNNCj*|JDDX%jlVxFP}=;+&ZTKsHa!E>15&Z0 zT38Rd!HbB4U0;!wERWD_p3B!5S;uf#nc(zKuwnZnSWEQ39^1CGOD^z8*aRl!5cjQ9 zEN`j-cPcULK81pWG3B`iWMw0uu)DRn0jkSgiHEpJb6L_%ijg}*z8kos)pj#4tOFm; zJ-nP>Wg34D2R;JK8lIeH82hDaUtbjkJp!K}=c#+m_UXOXA(nLEidC;oC;l1uq<_40 ztV2JPbtcIgv`ZJvh_~B$DSLrB8#CGds%4||ZoeGM_(wfM(`U;`{Xu(Dj?CCl-)M#_ z9x7f!Z^p_z!|s(W{u!Qz8-Lkl%e)(b+5HNcD_2TyHt$<(qqe+L?HG@&cx7;*rq|Tb z?bFO6a@ABm^X#1ZGWjNMa-X_GFI=fwuI=n>t4C{V6t;Ye5!??)JNlvMJcpJ!oL+l( z4!UpekTY(D`Bm+Qh=$C*iX>$z#;O2*2ie`W&y!PXVtaW-gV4uiaW{PHletXk8#eem@#LUzt zr)&&Yf(J1z^)ZrO#|s1YD1Wh+RF*2jwY^|7tEO+FDfOA8Z^3&Vjf7?XL|#Bh00KQKOF+sia*kn4 zpFih=Z8m5x^qni;ytqxZm!KP8eiha3z)-l{ZW}d5WL`l%8%JZC;!AjG3~k?5S?-G3 zj3Gq2_^p^zkmsy-CF+~{_Gjz=tN#2L3;p82#>l|e08ZSZlf75=`UZ@o)6|NqwJK`% zv}Vl*L|U;mCb?|iQKY%!4=hQVI*^vI_a5zcgzw?b`PZQ<)Ez&=QQ-z_Kchk|8Re-J z7gLFDFa=u*G5c$->?O&y!4YQ)JC8Sg@aC~gl_N`*uO=-$bd0;M#=J3&3ZQje=x{~i z-KFEY`4%-HjcxSPe3{bhje+}btdhK7)Lei<_o6GB1?bWJR3MAj*Lz}LHkY9%cagV` zGOxd7yVA|eUlj*T2>Tu5ThT$~&IJ!`zUf`O6lMhkHRQ*n-lDB_B>2%dxyS4?5ws^JF<9w8}umoG19^7eKf`bC`@p!k)-Ag~5f#Ak8n9J0-4cCzMh1 zY(YO-^hS4OJRsp$?#ceE0m3mj+Y6^wKd@qL<;(fdjZMOSX^*9+TE+fSr~7wYMW9uE zzZv@%QGTf9-F456`>E)prxqdv_)!0#+FE~y-6aD)tUz2NocaJ*WF5Zc8yswV{Z1|s z)ty980lF?2<7V-mevVEdpTAl241DbGiCo)C!FHl5U+M1KC8eM(Q47@;_QlK)@JZ@* z!PWazQOm-qR{Waz48vol+7C);?fj1bUT)5P386lR<}7HW?C&kiixV|?I^FH*&0juj zD;0MBWudDmzgY)9*`&F=qGcMmTwHdfJXDgdD-OZk3Ka|b1i&IKmTlMfwhQYx*yedC zajlFedyYjD^yAb|+UR~Q+>DenkcO!tzDhg-?1?I7{d&~d2OuRkNgx1D5rszJCgHzN z^=w~v9R+oB65+gVLFbH4sdFD-vq@ClO?^&aXAe2ta|Lg>1h(&q1^0n2@z3w z7HuAMtTTI;G1@EA-f|%Nu-okOB(9yMMDW+93-91Rks8!ytA4l54*{6pw}=W@nN3&$ zCn3?YU(oMf_;?!Y^u#faCAaK3H^2C4r2EvY%j2qcdpz3W-(zjjOLSXgk$6-G)|@9AArW4-)I(;rSi7@UA4JC z2vv(J&cduHMjlkS(cMq+UO4J|?5hKwK^dC*p340J!O~2yZ7_y(EcK`-I(<1C5v68X~q4CTCJ92E6 zan=bC0)9Mx8?$Rf++h|oJ;8(@pQIdQW-Y%`!Gh78(3$+h3)>1c#Z)76+zHX1@bD*b zso9*br<$sYQQy+#N4p|7CH4GVHDrU7CL-ruyk@=}xy<18>%X#9ii=ajMpCeL2b8}k z3@BVkJJw|&JtHnAbw>5Xa%*%6=yKC%4;0m}obZWIJ!63V{7EKX-%FWT>Rv(HRAdj* zx`sHxD@H7*N^KU-zMwRR`Y$|w+!6lxy51n^m2gUcXNiq1FF*oX0@NcRY-dz&&R~?F#q6M;k#;zJ^qsLri}y35LL)ueJHF6s8@x0KPIDhx=7pNes(mjKJ+Et9I5v5t zT-dRAb;^95+*f zq(Q$}+|c@QlO@ZkubkUKkm8kvr~HS(O*K<@llGRAI0L`c=jS@cMow3j#xEa@ zJ@m?_tFY8MZB;s#nm4I!HRNmDe#qXjaqsYD5#4Bq>JqzG0*wVIy*sAL*TDrEcAC{n zFwrnJb8^79Jk-EtaNXv_um{tFYK1G5Xsl^!wCiMF#g1jx$=Rpv$9k|2Hn60boA$ZV z@A*tJPaZ`mJFuoi;_;q+q8XqUGOJ-$S+=re5iiCxBkd$c<%X(`-6&?)XzsBKL4;_Yzlgm6f?{#M%8CpcT^P;X19ur z?0(3?jmll=-;MjNla2bgQX16GL7h5AaM&Pe+{nDfq4`HktV{mmr*;^XJsW0cC zGlQ~+b2w?MQLWi$IXdgNf3&3G9-^OW=E=BOj!7r~{4D0=tv$h*E(vy(M8h@gp_t;- zi{xCsQMZ9B{XNu$qh7f3r~5aOK2g`9`*9bfmJ*m*Nu%};?dd*}6WQYrVFsPLU%85wtGh`&qSq|--FJY&0yY`6g zFNUk*F?YP%2@HjDpbWjfPB78uXis=)@$JUyx?Q8oHYk&pBsiI6+_NigF3^O`El5wg z4W}FT8JCNvVSZ?`%ZYYAMB;tRRh4!hp|^O58&PG?|Fk_WgE7A_>bGy7nLjA zN9UL-U-v)bXRNU=D0J6JsE1RirChh7-Q*YD0GR^8qcIJMXF36XOmJ zpK<*(`S>9wJ?kzoI$# ziOg9)7_FZO1u4}})3Y`~i7MH_$kw)0`jJZpG9f;|T$)@C)ctQuSa?Yifi=V8&2Vrr zif_Y`=#zG(ff@HKv%G=@-TOO#^)9TQ(*#Qdqt_k=ASk!u0>bKZ6@45qZ~D4Nowd^2 z4q>e}QNBdE>j}x!%B(_!1bpOSs7^$MmFmpG(RWa+Xu-1%a_O-ApIK@Svapo&!(Pbs zjUg``=(X{qqVekx$Vm%w3=Q|Fupev52?>`rzpW8GKj^o~s#w0@FG$6zr@NV~kh-@c zL>ED2$B#LjY&_`t3v7ypwa}xRSgcgFRh7G30b~jK3d&k*=d%(RQ<2>RzY=^zGAlcW zzE8_2A|!wrCV|$k=yDrW&tfP>Zn0Z+pv+#l53^zLo#N**&`Wx9E?pe%tD;oT6$juF zoE`Uhe_Y_R!_Tez|-&m+!V4%_(Slf)6Z zetmj{kKo-$`6AmDNx!L&BK;lN-8vql7+UQfTB(r}A5z~e2Y1$I2-huL5?;wz+P1y! zeEdzv0b;wQO02B1dA*%Lz*lSOTcepdyEFTJw%xCf3Xc40IrekdB#K;q{7%+HYI$l78)OR)yZCAUA##x(j^yyfM#p zu|%{0-QDbeIbA)^jY{l9E!G)=cI+<$7`e6A@DLT6=Fimh7zS@cypDQmZ zQDZA>K$%ZJqqX!PK5LmgUwDz0EEPB9?p0WKwEXJ88M1eQrkL5i6`6R^QY#lnS22=( z?jUOj@T>4c@N8hg-ycovww1XX`c^B`AX=Fnd+_dhq@{>if|U}eEwzZR}- zp1ny4*A3<)4r9DBPLy0Ks%LA{cs-Y&Y? zu<}|x3N%M`WVx$3>9kBymVb5rL6$(>gLyEiKA zVRA84N;Sgn!^^yICrBsi+U4gO?_W&bseNn<4*^~RK}A-O9ojXpsDhbytk7_toQ!U{ z%=FU37RSNq!&PLKpmm+Q0-Xz-?h5$dsllu0+u0TK`p%;&E{EZX^h(=c4kU#jRnUz# z;Xx_Qb0M)=tb*f%C6@ycdVMd3#N)!4|56^n`QIeQY~*<*6NGKiGIwO8hle^B+=QyQ z2>}dTgUJ`?FDNepBed(h)YTjv8;#fnRkWE~?sCk)BvV!70F&@!soh5)y)GwbCI}W?>J)xDLL)?D4sQJ)N zd1n5D=qcOGbsiESph#V@nC*RvEf{|vCt|S{B=_+{T|)WDOMWOBi*ks-;z=ht8Vs}n z12g{#xVM!Lf%+9pq{_Ju@?x-<_>rjGAu`Zmy)jEBl{6)KiikMiULA$7dB^JtZn+&> zklmUN;eluL=|$AKsDQb((#Iaax&xgMnZTwXf}JM`?s3HtzmDRV&InE5egfjNXNBq8>+b zU8b)~lG`)dGYL;s}w0_wT3GI53MXof4!)V}}Kp z$g5sehGc?Wu+(c|4uG3%?eR^_^@He(WHTcjo%>1)WyGw$Oa9;OPBkwGxMq6q%6R|+ z&x&*+hNLB8h+=x5_z!6L-BLDlCTMMtP9u<9s|gi);Z%VcsV~R7-0tq|GfWBcgn?7V7t^ zVfRsZ!RZiqDPE(iYE@kg9TqdJj+gaEy>kOfwh+#Q!&ESp^#J}HnUdwDyaVq3=0^Zy z?sr^p25H^-5cU})#`3mTU7re*uiH-2sH=UJ-s#NylxAOO3;rB_sxfqCAKs%X^4Iy3 z7gW7oj1x<`0(WN1XC}*q6*idf*D#5YLcCt{Lu@HCzpLX#7r7gfuq1qR`4ol26cL2L zyoq|wdkH1Yzq-Gd8w0D>V~K0XZ-A_ zn;J9sAxR-Wi{{|->QEO4Ld0GQ0${qVG}hcx&gxMZ&s)Nd5IWLS8vi2$@rwrpM?wZi zjb?oBIHj*LHWK&|Ep>1C0P_}@bSCjd20K9DH@Y#shzN-DzSU?@uEjv9uW8`Yw zUqyWLWR-2=|Q*G#|O!dGQ8jS`^E3`y*Dp0e1tfv#y_ueD(RaMWPBB+%0;G@jL)0Z6tAvO z-nFvpDqza~fb4T^!2B8kQp@Ygism4h{|_IaIu!6?$bAV^%YL(eNWQ(xt~v4Ezo68YFWim`7-(9OmeKGO=;7A}+OzB7KP7*^$sSqza4mpk0pwm4; zFtK!Cccs6HdiDi5{9azYtT#i-OPBZ)nBDj*fZ-FOn-{;aBRgwsp~n$jGGnDmyKrmb z5_17aXE4z7;=x<*Utm9#Eac91!~EpTayoYy-_PLOMUA2#C+{|60Hm7?4*_^fO$pJ0 z_FnZ0e}B8LDIoADTi({>R{D2)srK9G z@9Juw*n^%D&y*yH8lg*H3zx*jMK?a=<7GC$JoL(ZS_fi(mi8Ky-9)v}FEw4?9`b|^ z-lW~bx+^KEXoSPj1TGIkn)Ml^*jmlG7`_eCPq2Hfj<*$HZMdPI?BAHkZmQeU8xF4OGytLs$ z3Ity&5e8lAw0Xy7po zGxYEPHf&=FMXyVe=80FP%8n2j@71rxzAB3^ZQ7;QYe(2i8`Oz-0{N9SA5Pw6aWlOY z&KK#KJtNtxF2UWh#ZF9~bVqK1>9Op2k<*^8M3b0xt!1nIm6#mnBwSHE3AY$_ecK;#Uc7h=; zDNo7M*Rk7<>RFl6=w_|TA8dLws-Jop#q$2#NF%S7p{!%2q+v0~E-ALUML-H))VynF zhz|}-f$rT|Oj0s=`;u8VofysnAJ_N{y%#eVwg!k2FUQSDVKM^d#i=dUI5$Xop^lHy zx2PdoH#~%Rj$Pr-N+U;-4rJx?*hSTLoFG6%R+>jSKWftzG{7Od z+DONKllp*}9%sj>rerFMah8|zUOJ7fB6d5`8Rsiw^~OK_2#g~lPpgpalvj(i*H)Dn zRqNbUrPoa&aCP$y+hXF85`wI_a2xb_t>9JRpAWK*Yr2I$;fuS~VXp@2*Xd&~r8^$T zE{1T5ej837Zuf+)!Y#|-+I=lK9!Y#sJ7GkJyD&rZz;VRZOR+5ZIUBZwvCzRmE=@bn zqJuLM*i96N&(zw4xLoU%5_^|7B{9_LAH6@D@6||W4-il`FJ|LO6y)A|A?p>+-gH3! zq4s`OvIF4p?d&ubmfY0esD(32O1VUB-UE@!S+7UT#Q*CL<%ulq{Fa=r>-qBp`T6-7 z>Ga&bP>3+=<139y+m6qS+fsOmX%HcG=}siL@8#+t(7uL^L<_w43=70uLOXldnT)6} z>FH)Y9QAa(THk0V+^PT@aHp#x!epFhmzz4jQ4YAB&?TG&tmm@@O0-q|5fvNBjNl5MxlOu-oF`L5q!?( zUN)jeqL)m31`AR*5Q2VB(>hhTZ{f>78##ooGG6%s8;mzV;tlV4~GUWFZlN2 zxsBI64yYIJGXK%NV|wm>=CsWz`yWeJl9a9Pov>-3)W^z1f-}pI%64gyO!umEZzT5F zTxU5yvf-JF+7^J142+z{SGRWbmW)0upAueXi{W<>4ZIT$`PqY4A7G`LtjsUtwpvHu#@@44jhH^vP*Wn3 zaJ6lDRzh`n(&-~XF#pd0;uhuKuM?rt`AHbjgY6E2+(~0QQQoNpX>*c&BA1inD&cgt z1t!rt0|gmVV_gycpQvG?SR9DyH1COoQ@JHmra^?dd>6&T6n%Yf11w-ZMW7G1M?Zgk z55YD}A%XfZKZGH7!h%wf=c{2$)!wpAQ`1+Py*y=DtB_`yBcr3^rm3~{Yhz;w7sQAf zHF^cK+B2@yr7Ly5W^BM(h1TJ6ay{1Y*Q3u#sd!U=&||L`iibM=$%Kb>)+W*VTy% z)Q+>XX^LyM*0^dl(M5k$MQp+eFNZbmZ5$IWc^Rv`*o%({@mvvek%-&!&c$2PmG;OF zHWqd6)?Qz^RCU_>PQe0R%lse4QYqaGjS8NDQPgKGlxg`w#%7jU3=G-m;YcnLzq%mv z4)0`tUc{!;v<6-`p)X+wgoZ|)_5DLkWR@byf(&5Wo?ndUuk8rE5b)kf?Z?R5a=i0& zk~41-!1|*ZyhsGvgo7~Z$v|_2I2pke7q(;L+)PKfr{U$4Mcg_gq^pi)7*utXleAad zz3=oo19}OkCo@!R+H99wI_uZ*(-8dYkgY4My#b#PPr_0xaKZ<2jT`{?0e3k+R<}Nm z(I%lCPKfMPiNi%|lVY_c&jRl{LPVBa8fmIBCc52;x%wYZ$gmA3Ub(NEm*H=lIflJc z24y@%Ae*fl2r>I*T~x?Cjcl6Imf5YY4Qu0xOE=N0uR1YA8xus?+@Hgl|B8R^GHg3P zRc{+@KR}qK0Q3T$-!gEzhz^h|Cuh)*9bdSqDQ{w5-bi9)6lUan-G?Xe+gRQIm5Z&I z6+$caEiv6g-;3&@-*PO^*VCRAo+9t} zqvpLgj`!`_bLn#h>^i9#Ns(qX6@^JLnKYcLly8zEhzOYQD@qM8yF?x5L~~@{8=3@8 ziC2WWsu+pVbc+6jI(5yMPHTHTQ=pswz07QO%}jb}Z58vS?P%irulYZw_1}iRG*tci zZl#qm7B(=;{Z|#piJ@BW3a@s_{CCUJ{v4fPtjmlZ54XPqKrD<{SFlvK5XHL^0(bQf zO65wrlRmkJYh*$z5zuCEvu$FJ5H5-8F@^oU_qOmyA6;5QU8Sq3Ft+SsSPln>FzN zN(fs;9r?1Fn((0lgc+iv!b3}+VRm}RnOvlcomu9S9y=)nR;%a#dOKUG?oX#|<11-czMxjB|xtL=ow_MN}a$TH8$^H<5#;-HBe zz>7@e1T46p_x=q}!IEI{djv2Es;+*4V_8Ri67^3x6Bsj3XHd%1gBZLta;7u$E^$VN z^SqQNSb2%D_G4kUTyCg3UUGDjkASe~c~Z>K&|Xr^xGJHTxyPq_G`C@Q$Id_g4L^pP zXMPR}%a8lBLd(4AoCZHVOqX__EhmF|wxbB;zwVqy?QUo8vX$dT#~~woHecW9e0H=- zSDwilZQYQ5pcL?4@B6GWOtk$n-=J;#&EKn}dxoU^Ub>cb zUut?D_J?hOWvqogG?i@^4Lh{?UjM`3VDe9&R#l718^_0guFnUS%Z;w)p(U*IWW8tD zw?pQ?TD2s~cZ??+G#~O}eK23DG+IKd&MTs;-e)zkB)kCD-<%+2U!oGXmQ}XkZSf&z zY!73eXEO+jWL>F>Vd8BZh0^6Kl!`!zRKNai(TTNQ!A5bPHAzgr&3}Aco*nF)Ek)73 zZ{Dn&b5)%-QcoB=+34%5D+T(8#O8>+6owN2*>9?Cs;;pN98dNP({r-%iND7*Gv1uL zqytvIN*j8q?Sf5!u;}}q>hA0f@r!t#Z`vdrG!D?mLwVC5``X(pML%Nm>XK;zUavNh zW1=vJ_rYZcUbH+*Gak98OI*=9tP#~%%!?I>bZB-<=t;{QO~1D#z-mS-x`YW$v3h$< z5}5!kREv%@IYv8=&5ApQ>@&G?Q3}Fm#o_Q$0Xk_z6DjF1YyRMN-r>jYgxNns zQKEyADKA%ZO&wHAj|OU^$J7{}aS6U6Ph|r}TkqYH?t?+DA$!g6s&AQDpP)u{X`Pl> zYue5HLB&tu^A209X|KlQbt7IpaGJLEU3-7k)DdK+`qBzNyXLObX4{ZhrW7k;7t_@unjQx=o)px109+Pl<~{2;G;y>$6$e z50{0n9mgi;=z9BI_QIe2n_P@T=yo6?N;|djjUOtkK{m=;_Xcy1P2@*A# zM=DVjxQy`Ic5&ZnAN4d>`#ALD6*>hImR@T4timaDe4LhUXA&2vgX?o5H#2Z~n1Xjc zk0%~PEx$>2nI2xGp|phZY}8tBpfmegdyF-~vGu>=j`=vwofJ&OX|>MOd9RYHQEyF(vc;i-#5Pqe_y|;kyYqFOUgzUPXCjM zgyOPDopmfk?2IzfbeFJ}_8>YkWn${1)~OUvz_%`fX`@bu8Voy=c{=&YBZIoHO}{JC zC`E_v=|(%e+({$|EH+4p$tQQY-QzK>D~(Cg9jf~NIqC&Pf#H+UkmNsS51uecJ%7e+ zYHBvIX2`c`z-_Lo&uZQ$A7zT)C+$7N!a*}yv1Pr>br&%IWUN)=P8O|Z!5h^L3!Z!t ztUl<(GV~OQHE+pz@!#|-JN=}7(m&KOLF^=M3mLz>jK_u?PD6U&W6=((;luSoU-_Sy z{=RCO{#hH!9^Nf5CZ%#wjo4&mD^rNAY&K8G7W4q=@mk!c3svwy{hJ#iJ%YG706C(T zy75r&Z0$cIn-fP=AJG^;rQAVjm4xE%vDPFszB=C3C9+ayYPEQ)djHiK<`^}8pw;+E z>Wj=kfSY-)C?VpwHq>4Lw88zzRP$Q?<*n5#bIzXeFHu z?zDSOIA1%Rjz=@eP_$uSMQm~|5_JhyNV(mL@O7EWt3spHFG`AfIakJ#deG~2-aY4n zL167mtk;7RvLHgI7QNfcW&1VPu;F;;aJ|5aFRP*&$yV5UXGaUi?`hA9?cBNAr12&Q zqut!B$w*wx?*Um@F_5}$lW^df(|Fr~U$N*Txwf7PGU5}JGm`$)67O`#FElS4ivcS+ z6Wkni9><6ZZZ4z3A19pAl)UCi7Ha=&;zB8OhN_;1BX#8;Pg9k+kEXtFWnE79K9Sq6 zS}%P;Q8+fY6|d28n4dS-z%=ns!Bkp?Yp8X`G=lzw#N2%y!xYDLkGg4{124*j?E9zj zILd!d=q>{5hc?c>c}gvi?4o*l8vAoRK*9BN;=C>@OOju7u8lh%gO5lEh`=xsUtcFq zw)aN>(mf!wU61KxWfO{u`JG$PcBQu*9Ae3%U76Pbf&tuYNDCZ)bC|0Kf!EzdSp+{J3hC*;n)*H@0jHZ)WZw-aqyjI+(ebI zXZiKWyvtH6&ol0eB!YV;KSIh43bew3Yj}^EW_b;Yg~t*O%Xp;Q<+8{44^wj&L>MUy zmjCwUBni^mmk_0BYvX#bLq42#dDbK(nZyZcnHc^)>N0QYB=|#^WrOwce6}I`PryaS z(}RAeIXZR}$ttthvFC~>$0XVqen3>T>$p}_fAE30J;>8G!hfF^@%4jk#7mrwEzeS} zF%LtTrK{F#Tgga$H_^SM0`}aQLGsv+!tr|Lo(7!xTXfh+toAngspsWR?$Kjog>&M% zw!1+%ny91ki_FmOtp{X9aia5F&<}jfxp)ZQ!*T84zIL0y4P_t6wrl1?F z{ao@asT8|n3=6Q1K#gGasQm`Mu=g0GG$}KB(mB|szuyMr$@8rKj%OyYB>6W`<@xnS zv}-tQ%jPbF>aCBQ`|mo9%Ri3{uSaqpVwO@REEjn_KfRN&N%GlB#zlJHm-;PVAmKXA zS);vjv_S+8_`8Z^9GPF@@_f2+m*ajBoYKmIew%K%a~5x%8MSdJF+ZrQKb90W-`*z1 zLGNd;+bcySW{fXKN1CK!JC5RB&}3Pb7wdx{dS4J9&_%w&PGPMRze)O+v5KY;Mhp(K z>m^im-n4ySx2O}wYF3gTY~CthZK;+17g1sH1pRSOr2DvQQJ^ygX~^LS!R1-ZjB{^7 ztQ-v~ZFCB5Z)XVa7eQOlVm?Y-7G3>i8%AvN9gxCXm$)BmHN8rEHP9scPJ2a*OSn3+ z|5lzea*X>BvP0`+rGKvYX0g!xxiwGLjf7~MD7(9&1vd{|8~ZY(PS(~q)}y8x44Ub1 z2U4(drN>-|m|XDNXw+$AUMA2%_vYC+HCqVqOxN9u8*xNFhgj9fx{kUAmJ1*jEnS68*ywfbWr3gO#`q0$3?mJ zTGad9|12U?dJWx~m8aNnSr^foa8xNI4A8hOkB7xd6Bw3IDl+nI`GQ@T6I~^DsAEAq zNMJROOgpHdKLd^zM~}_`C&)kg^jDAX`A&OKi)C(@rAcA<#v7T3$%`Ur#KrS1Pmr4v zU+^_2{i5wL+B_u#PP!WzG}g0$R0Lu}!_6F(s{u-U*TkYYV-px&ZOu^^{;DFT^vgzV zuHmd$kYE|LVH@MAoarlF)SH8z*mzY zog%#)D!VtTg@5$&Q6O&*^XSFL*z1xT^8#sxNxfxqD`#3c*ew2WmsZ=?hxAN()(Kzf z#0;nvVLa$qQu<(~r0Z+p<6K2r1|0_e*XwFj4`8|Vj?$)~J_x;g$HPhR=Fi6X!8o;F z_F#plw*sIQg=f2KMLqdyVcHznm@7y9KttnSUucQh$`w2>2*uA35pwkb=Rx3e(>Xfj z-v6~)lNsKx!(aw^+L=wYu=eA|wUWN=!EEsfeT0;iyvGb01#vAzyY0)ra9~3}C8MMAqm(#! zp4AAi8FXJkikzh^pX5b)FcC~ASja_a27X{&e0Z#{XOJSIP@>8NE|C<4<-k!Ep^L4- z;=i+yGE!2>%OB!J=29%(?!t$AGik1#H#?hLiv^gy_;jnJczjs)e8S=U^J9;N<^0DP z_}-sMg6HSz#2=p>vZbVCijh=^vLHrj{Sx(hr!9h|H25ZHHKZ0 z6+O2qAv!&a^Ie<&*$@a#@Fi-pHF+?=>2)E zu2_(NQ|m+OMrsa>Ag^@ni^e2 zS77WZ3>Kw!vP{2QEs{rhj^6B2EnkhH+waA!e!i+(4FNDb*F2~31BPo|NUPN`fAZ|C zAt~T9GKKZ7nl5WA9ah6PrtKF&Hz1t0n5`sSA(mjK6wkHXczQF1(m&!;(VWkFk>3LnGsSdgUu(p+Sv_7`I$fplw=*R!_3 zaxwsx35Q#PJqPj}t=j!fRtiFht)}C>+C5(Oklty~s=u9kwEG<>ZUB9GFO()Oo7@YZ zzN8fKeTlJN$NKvn7|GSQ^7aNn+f5@8ascLFM_s}UT}`4zc)G z`lY#T+bniJ6Cq0SK-hpQe~y4NPo;5VqSA+KrQh?*+({lA@iBX9WLuD~fs+4P46;e- z*C)_z3%g$a&uo~bGcD|6Bbj@2B->CbpJ&ro@Y|D=Ud79DYOO3_eM-tXje?8n!SEAgXH^uH|&_!gpyC^xr$>y95#Dnoz+?p z68FFndtLN&AsD%`XOv%Hf&cJLx0)g=d^ed~zD=a?ur_RfmjW4LgSh~pLd-%)t*Kz2 zUPz+sgL{mp5JA{}Maa11$BbIT-aOcK1X4g{yFyzP_&PJ@LGN4Tba20*qws z3dQpS&aPzwE0gtUXT-%_2)9TzHGid9eQ~Rv_fM*3V8bg0-q4rl`ysH)-2Y8f`dRM2 zBIc?AU%vZs<&OuI%z^G<>+qy2(PU)x%Uw!LN_=P6?VLdWRQBwooa@A(;HSv~WPz=s zCui}lWY&eHw=s&3+IZ$gCqg5#hl0-L^1M`svfu3f+kbI=GC?>K_tnn-HE+rVjm~K7 zZ}I*cyqvF|y>U9+OQ)aC`=Kk4RZehs@NFTJ=8x!{=?r4h<28hc*wIGR>V;a0ALEHy zsoy(F89KH^DhsI55FjZ*P8crXt~ZiNcp-iL;<~pFYp?FgLQ1XOxjh?F%quuujM193 z2H*y^rUFt!&WbtyEyr_7Sf=M9-p3kg^auXt_m-4>;deC03r_&x#H=p&)~hQSSO!~K z*|nE^W2Hq&r)6%LVx2NQHl~QVF5K{Pl`CylxKZ|88Lda*{Hq`Iy^mh`Ozi`0L#eyv zorCU&s1j#Q$W?Fq+zgOIyM996_Ff?8D`?+!*pO~IHcfUz!B=hZy0-+dhhX_eQbG#- z>EH1i>14sE*h4kLAAZFxtq^nA6)s%_9i0;|*OOU8isM6-VGCpe!Cv3$mH1`DNf1uw z)!p4~U9qU=sl%z=u99??pP&>hu=d%a4p#`>;2W$JqE6p~Q|5#b65gp85$6?S8J4xJ z%!hvv^Lf@3-!>A^zGMP* zP4z!CU}%^u8EK@WG}i>xnbz?NWC^L{R<+aL>ZZNx)qef7N^2csw@0K95P~rBOKHn9 z{HhTr!dmkii22E3)*lx{{N_z4)F*w`scYLs-$rUR&*1Ok5`2vTW**rL`|Dl0 z;ghGcJ!_VgaAxoeGzFXz-;{4Z2``FgU+j`o9= zrrWi{?gsXM5?~H z-5Tl39~M}Ln~PlA%HNQv29*M-qlMV$7D!mort{ut*9YEDIU@doegHyaErYukVT%sG ze|BGr)7QWzC4}@VfmTI9hR!E-ijNH@T1`WPx2&m!66aKM1o6pG=Fv;7jU7U-$-ghq zM|h1$h&ZdKS!Hg|n4hr`h!D4+7Jqbz(ord*I=4l7V7~6JjNn$yQ5` z2`A+X?YuUy(atXjkyXf*34T6CHVQ4vh`;{|6r*ZYJ>-f4Bd}iAWjp(?kI3&nZ_Qgi|H1U3tSrsS42MbP(%M3;XHu76(K#ljBF1$D_8-bn$ECbrAM1(lBM<778e_(gV17k1stUL7{Rhc`@OG74fFmP4WBXl8i<4m1R5Y<-g?@5(j%$++^bj)_zK`w$IEns6aK;`ynxU*;2>0D;_Tz8WIJR>y`{!vTVO%&f^=WmjNAbax1 zx1FWJ{oW2@A}__o?gxrOo!*=MYu`{-y>%`$dgU^P4k$P9>PAnDmcQq8`~Wa+U! zNg_U#;5i7L-0|rHZ9+X{b`(ev#l~2|Rg4w2qn8GQ#R73x5xLP+WcZa2Ol5H{O zom`CuKp{tB++AQ@5@Mk@NfI%r1VwRn4P;h!aTC0SI-1TcbL7I0fpkS&U^YV!bx$*f zpwY0dupes!-ch}hl089ZY6je}aXNtHRRX)Zf`CwtSy-Ci0(+L+Eg2G&0%)pb1@Q9GhJ38uJjo_ZXJafWeBh zkS$=HKa1ry1LHq`v{?H5tIG7bq7u-}g0pgKI124hecgm@imMq+ztf!*ZiiWnoly}U z{BB;mxVM`;e@w1pp7K%)8y#V3vWByJigl+M&Av`}cZS=CrJc%TXx?2rGuAF*kM(^5 zl2D4XmjsZj3fMyx<1h(n0sLoduw~!E<7YMk=YmgmbVC;w_Pn4>PEf+;Ps%1wNPicp z5^@<}2VGoQ6gRAp6S5?V`H2%QO5>feEdALI%YNZrl>^d#ZzK+92bMe)0dH#|-o=5r0)*Lqzt&!qSY;qO$4ArrKp}#V+ z+7RtMv>p6JR#cZq@u0#izc1|`dSh*o`TB30$@dMcGYOXa2s6s#dC_V9M91}(HRirf z;cMi$A`RhdWRk2RnuVeNnSmW(+(1l19=_-Qe~EV&H@8ML~p?txR)P*rB4jj zYLPJ*9|`hq1he5KmMyte@pcR-_}VFVKc6qyUH3w<^G6M|BcGjj5WikV!Gv9oi>4KI z&#{$?)xbI4I+jV(S&#t{%9u?A@Eh=X)9oo1whr=B`NkGroJy7TIxafQJ)R&V`L~eu z^_KXBJoTC*?#Qk&%Q4Ou*t$Ub3xH!#XFMbsgEcYkDWve%+yfzc-6O@`VEsVjqlaQ% zFj$JzqK>^dOAhweRt=``5LU|PCb|<|z&s2kbFMuy;tT8u(jOziSx9!!Dtnzt{ML+G z`RuvzaAAb^09v5cR$NLJQ&4=Jlg5ywms5YZ6E&lB#scVCIANj5)A{ZqrOHu@4PaM} zw8-K9q8!Y{KI~~SAfDV-HuKxjoBW#*G!~64$O(^?w2M)c^H)f&8JQo~$BBYe#8f&DP5OIJ>bo3&s6uyp9S)2ng83Cg^WmV%Ceewqt!*&_`Vad+|J)Lsb9 zX6%J}vjx`3=0~*q;D+6x$ujxI!n_roBOrz)&D>k^tVKJ_XKL905UfveS?!)+0xr<0 zMiYcc;v(HCglWU|YIO{>3LqbVv%%8vlWPoPA_b4*BmbNb{DOz(OOG(@K*@Y+@!A|5 zC=-bkG0~roM5ALrcA#^SU)omJpAd7IWK41#N<=Mwg@gQX1tG0 zdYBmCR3?7whPpZeMWU+?s8!Fm^XWvMkUBOnsHgBKiZFvPnQz4c_S%dcsY4Y%OqDR) z-b8)I+sJ7Bu8st~+D#ag$f;>q!ey`?K|wyXf>t~yThEB~Yrnf&18W8Ph5S@6rQgav z)0)UHZ-24q+!L_wK%S9l{>~JWDGuHqnNMt3QlhznrU!4lQ3z9FEQ5BWD|D_2-MSb+ z`(Ck}9EZ11d>LUK1}}VH`IMyC&jzy_F;n*+s%Hgf6jS1hQW2v6W-f;(KQ$yl+i)i& z%)ej!a*ThQ$gF9Y!9}v8(F+Pnc$C=8^+EPb6i@x$O5st;FZaUo3f29Jvb&@kob$$= zm#hwh2%W(3E9X@(K8BoZehxoqutzLt_wwos8TK=5%Jd9hWM;0GrQm9G;{XZ=*!``unlooi(4-b}!zLTRR%s zgSC(kAXA?$#a}2_GG~{aSKLuFJhC)~$sFUx)4|Vtr@Esxbq`rAO?VTKc?eIU0h{*u%2j zEUYxlm)~hn0F-gI__0%@ryW7z&k@JX#DKaKOLsf?8RgY**zF7@vEz(uq49GeuW3I8 zIZDd6!bo^g^CKnMX9k<{ddZ>3f5L7emCi}1CcUg9Z^SGmUrCIyL27=xhkM(`+`N}_ za-Cmij4yDVb(OVwgup*={dwS2FkOLuzaL`(a{xEgeIR`D$O`W}XE>a1n!Qr@?_Z5< z#P}Zy$BnEgMLB`*#`R%IK-$V__c8C$Dly@&{$E@%)kwFeHOqU|tZFnK6fDHG1xqh6FknSL97 z32C}gh^25j4D~jw)xOhd7eec@^cFzKdfBH}4Ex7I_GtIofUx7s%>u>^%ZCR49h?WZ z#a=eBz<@EvWi5~uD0~v@0<^c9a{zKkq1F9)%qL2K(fQ^^s1$&bdp0yZRej7)nh;C8 z$OhY@jc|?ub1p7p?AHAETRv#r;_G4bVoc!eSf< z=dxb*c>%LiP@D`Ow8M~CQLapxapKdgdw9GavIojv6KE9OOL8W7Sthj&43_V1D+%kN z>l`jMt+T5QN)E0gq4#5FCf{27oNcxbi8=x(R?>VFNbyt)iIZ!7qV9zZ4J>~dmV6M6 zw;b;C0DApxRWSgfZmy7)hzHz+t!>7>hCx+?Hs{mVv+z0|5O`&%)a%~;^y8PCD&$H6i!8Ut4=aqY{FNm`0`w`xl9T!EpT4~DTNtk@DL}1aT5_h)WZ)V zPlKHEQhpD3c`kinPl|Nqy357MYx25hZ&iMRuan}~M~(AW5}qb@j9fAKtcG`gW8-3Egm9_NtjxW&Kl8DLk_rrnGS>ux5SJY}ihPuoMiltBamvrYb^@^E0wV{(_=pE6 zS&gLv&d@3Nhr>5Q_6B~ASE7bK-$cHQj;}>5RIs0K-wx_xsz9dt^h7ZAX>Dj1m6cym zW_5SXTRdx4J?B2B#v{q7*gYIxunTkU3OL^nKQ^hxWK#N{o2f0b)q?5GwqZ83S_}LlnbHqu*|ILB zGi<`n#hevGibul=W$S;HI0Y@V8|3r}G7^7M;wBw70@;`keS@Pgsd$Z^Das|2;(JRB z?BRcY%M_=|YFkbiF^ZXNUE2?I5n-UyKnrBTh8A11MdZwj!U{xVE0HVuZ*|?kSi%3I z-v#0XMSDkMEF=RoK8M?g;yGkjD?G?H;x1d(;w$fLNx^-`XbsWB#TScZA@cz2WNp zeF21~hCVCQma`z_?ShwO${7&r6QcF<3tWK?BfT2lg2TdaTie+_tB$&^ACEUZ!qvMm z=*HFDvVi~$Xm)sRlLp|T-O^AdDo{?^d90o6kr5rKZF2u3E)$HqlThbDAUSw+M%FF_ zu#$K)!8i-6*s1cYmUA5i`2hX^v>wog26x`8V;|%hiTg)){aBDlyLUjJyi8siRt;MoFi zp5wm;V0g^gDxgv8P3rrHt@y_mMtU_ZZq7ZyZ~(eL#|YB+Na$XGHAIM&fuW800uZvd zHlo7!mxB$Tk>m3*VRa1Tuu62OT**rK*AUa%GZh&3&SyNBwEbtG_G_z~DtjmX;#?-j z9cb6HiTw(3rN4nCj&1Z<*N75{?voBSoKSJ|6Mn6P6xc#;le+KRNXXYD{F=%Z$ffs( zr5UMXlpl5vm%x@5yrxpjEkCWm6&RwX1+MN9=fyL5kC;Mb%z!0!(f95=(K4wyw3un3 zz}=Vp1PJW4!W4xQJV_?`@Kn=ibZgsGvxrwqv=8e4WkjXJhvIlw= z{q9a3mv3*{nr~C;IJU*nG02nRr6n&NSswi3w0#Q|9~^UmhsDIo`VKXs!B4#Pu_ z|E~-kG}&d%3r#yj*uE}&p<`G;_g$VT_u>uMLq1I6=&z^MFts6&Sp1n1@VtN~!TSYY zl*jg1wNIW;R*kBQwe{&WZRNi4nke;j=nfC;;camDU)Y)+-PG}{-N$y-qPY28sKr)E zv0tAOU&oHLd}r4WZaUh3Bf#ofachFmczCwEeTyjh^X{tw=fY9s5*K*U8#0>lm(YrN zH_Auyg&UJMnYXC&QO=Xj4!>=A{`NM*Pwdl_<;?_DZ<{R@B%VYk^!yCY?Dr1rmK}BV6hj^Do|{^Q-qj4 zLx&EnUoBp51b#*|z=0>YC(AFS3JL!7Yi?e1y;_`A&{`t+xj+5SeaY0%t%8cv6SXUW z#x+%ZWb!T+%kQlNjE_f{=ILEXIh$>-oWitoIjPgejQ9;l*B z&G)(JyZp#+fsVRP)bfg)CI)YB!W%AM=oh3Ov4X8`lw#hC=`UHRM_O^h!A6>WzXbA{ zl1x?VUs3%DKku3JoaA_WvZH`jhlL1LMep~CW^Z3*vT2uw#XGFk?WZAXBU`g-!$uB- zvcy6VpExQS)gKyamSEuHV6CKN6?kxO>eRLQZS{{rC0KFRj|cv*+jEc%*p6@JaV0#l zk1#*U-(4a|GU#j52lo1<==v>6CcD4gR1H3kPjjc7;}-3?@SZdX&W-OLhtB6OMhvLq~x$k1T+uN&`HdWEuTuV(T zeXK0XWP8oGWTFcioKXh-MtL`;_~Z1)4BL40`t;yQFZYrXeWbRy$<@$Z*nQ1!BNMoN z>+@LRpy2P{aS_K(yk+2X$@4pFF|*0jV?Ujw*^s@IO0Olh`fbzkgC5$rB5D3t6#X7X z5(ySfx&Pw!mm&4W7dI7M8Acm#dQ&K~w5g{`1DHE+;ns%{wt^rif(2@5VJLt{gKD!%~ng`weU2{>Hzy*1Mk1_fok<9u?{aP7p>ECKecrB{&h}`O-Kc^ znVI3ewbZ*7Yx74VuusS+rcF4y`eUZlVsCKH$-Kh6@$3A?4l$y~(J{D$l%G8c zF$Y9Mo-;qe@+NB!5~Sv*v}}%q`<>iKyq&foaOTxyRlhc)&;L_hK+;3DNt0|k*P7dy zoVX{JXcq_DUTV->79Vrn3HaRl7I$?GWyBu2bbD>u)b@ZWc3AoBtb_W-BYgKJ8Zhij zqEA|t%ek6bryH18c}e}E*F5vuT%%4o?BLTE$61Rb8>#v5EBKFXI`>GPp^W&j^C0SE zRQK=s_M4|S9zSA6zg50!k;?v&s7ayXZ4<^qvl!39cJ;2!*a7j($gVEeTleaR-#g1J{B;NX|<%$KzItIP!*U8V{$}4;}@0 zRSUh@m<=sWy41qEkN7aq9$hzqwy|h;YBa}BtI|qHf1Dj}@b}cfWlZgUmc+fNX&w<9 z*_U1;vbyaaAc%EC=2r3ba8s&wb$XN)Tmyb#{g1=nbJ3b&tSya%mD`gb<1h4!Ou;=g zvrS6Bi9LU&F`IncyiZDSWUiF4!{*S>zR7D}{FQ5!7Xkmmo4v&;G4?KlP14PGF}39R zPkDER1mAW<>W7BI-FEYz%p&Sv4Or-lx@x&y3LZUoF&l-5s34lnt>8wQ9D(~Z_@$0- zW~B*JFf~nHp0no9`jQiU2V1VM)UzTMbq#wII|W$4y>hVcgglJ~ShIuP*&831R|W;; zcdUn^bEPd)h@GNreF7m-D}gJru(Nx=h6L>n{4kn#v=X}y=Mujl7@V}TGO;oy@amDZ z-`^x_x2y6GFZu-|c8lIIQH!6q*J3B5^6p3(N%1WL+vK#oGF!zIiS-KY$2m4tE#g5_ z44k#@;{*K~yK9alX78&t<$JkP=nrpom$Uyax^!GhT6`)q(9q7vTo%6{*V=sRUf;6Z z$iaL2@4i*_Iy4~fcu`@lOjuqlTI1I0gIB=oAIpeG6()udQvAFmjJBRVtvQRRcsj~Ma1mnEX=@bt;`w_^0VA5t+{i@_&JGS9 zaH|2-DhG_eYnp7C=P=jKhLjpeuk=vt{8ViMgb zGJ)#$$!FSOhiE*FeHBI)F*dlb^=*OwL}64o8k z+##X_G5FEBkK_9gzM48}PXAL|)88jNr@ShXY!)ZUJ5MH57Pk0s&vm!*D|&Q1`-!`v zxZMHG9D+)S-(?IT=LB6{zO>(Axr(>Q;>v6lQsjB({EeV&WuO5O!gLve`nyd>%L}%g zb%+fD9cmeKKs3!t6g%GpM_Fe=3Nt)o%LR6i@6szF2cm-!^g-@?)w~;Ddfktji&M+gXcJ){Nhjk(KRpFg? zcp#@bE*Ga_o59Wjo_C)sK$#}opI>%#NE2yNk=#(oyEOiM?kJnA&62isRYHDc(3Es{ z9im(#OPafmLv7k|zv1I#dR8?X#D1e>HomS3d0%jLeaU&Qe^0ez@jy{)0h{DDE;Ya~ zr>%#(=7_tt!z8V&*n(wX>?RdeHR94jsyu=Ib-|{m5DuAeT!B9Ht8-}ypZp3840?FGm*P))dIQ?o+w&X#=S)SIM=(1C!#;KJm0%5 z;}38nd@KPK3tmUYX%bsDFDp{_R@P_%ZF?aZ`$zjh(}4U5C)k4 z_*Xb&Kf&4Q)?Z<8GW)?i`o!D*(2@`uTnc$kv};M^u3Dh&vm5+!TOS{M%6$hixPEhzaOBZ82(B$a5 zqA5NGHPI=49>lAD;LhwQsPHH3My9X}3gT$;hwoE?r5aB67LwHiU;CZkkuNEycMIyZ zs>wXsnsk*JFNtJrHk(^h;wPtWkD4}KcI8vuKH0|ir8{|L8j8cj<6uSPq{U{0%v9$h2Nzs?V{)>q=o;K zYbHeXkU2C+Dkv&=KzFk*juYSNBKDiG(DAw7y|};Qnl6QQWCn5+?wv1ZjrU$|?mkA-#&$`-)>FT+gaqXNH{>Dx%B>Q?jy zzlvM*7~-~cR)%#`Q)0X6FWi;a{*g74wC)SJWa}H)wV}iYh1;*NGlk8(SXU)y+&aI1 zt!Y^H8xrbn4&Wu9mt?a&&Ywhvu&eJ;qUV0u%8|JP!?g2Y)$G^>ONcJfLliq2%7ngRG6RC+67DW<;*{yz zef%zLDW0=kJ3TYlEFY(#rtL!EwfM({QjKanF*-@m2FbiQ(F-&9OgHkJqDvT<7rTZ>rxKaPon9ibem-I{+;A?b|?E;vhr zI@b%0Yar?2LmK%10%-$tFm94xa=iI4(IA)nG4&;f1lb0;uBPV2(KQ8jX(fY3@t7V9 z(lmS*tZ2OcL!TVqad*ZM+vu&Lr^kPPDVw>@ps z*uZ*OIuw5gH_~uP@?dTZqH`V2^o04G8Td@Z7hkwS*n?PBJ)GS>=Um_>;Xlsj|Kc|0 zQt9?9yy$1UXo(cFkAXQXAsTMD>Ge&g-zmyrG|fluwYur`o_&@Z?GJ%H3k;X& z3rvK(u1LOW$3_NzQnYc{9T&w2g2gglV6pm@Nb74YCY)E)Ji?+q7jVb>AKwPN_mqf~ zxvFE}pTvR^1I2^mzQ;bnzZf)Hl_i(mk{JSD@DgceJ{e(q;?idveaB1gA{@?E&>!1R zl1WZDQ(xJ2&I_Dg*R4@MypJN;Pa?qWe(L?5`|2qtk*0n7##6U8)@Uqu>lVgYa1Aey zsW9!E-}#h58!?g3RAIyAHE_dbP2b>o0-V*bKg+0#|K5xq;lW#yLG^!Lb>GcjT8IdJ z4__Q0mf(Av_4azm`E`Tsw3|OSE<#bQBbZ{fAwEj$Ru?6Ke^JX7^6bCin%eHKN5a57 z6&W-@z{7?^d}ZaVz#|zsp&FDm8rQJD=&L*O3A_ZYfFh9Z|dU^sChX^78p%oJ<3P9Q$53 z`t{Z4nUo`=#5YC+Ii>U$)pR04u+kM1UsQow?Q=)vWAb+m~bB5q*F^-3|nSDr90xp&fK-mCQ$|B zrv?9vTZ&mlqDJ*#sFg-S%H3giX`88?LO36%-76k2gN%@fMmF0`YN%FK3i{jpkqA5X z2tV1PlHI!ujc(9t^c{T0K8ME{{oP9X8^+B?GKmq@s8eT^S%eb*k#fhI54Sd}t^A|W z+9FpCc4aQ+CV)?&@ybVGwn3p7NxF+uH=_RNo-Z#Bnh)udL)XE2!*qC}tadjPC=5N0 z9NrE#`v$il$Ebq*MOK`}lBv+3GR#FDyXHCgT!tX%#$~!vU6tTd!H%jq3niK~7*Hu8oD8aBb~lcWu`@|cENP5i?#s(IZQ+zQqbHdG8R z*2TbG>g1H4#P48JAMALFxk+U%MZS)OurFRcsfe6&QJJqY4d1BM!a(M}&GHEP*F?VP z5<8!?`oe_ff;W6HY4pW{5KBkhY^LhR8uLYEZgnv-ZGvr(yb%;*oAwrJ^{N4i@zhzT z&8ogDrZ)ApZ5sTjE201u`2l4~5OF$4bdkHdULQUb8#Yz;So5VI(uJin$ea%HMn%L2 z$?y!-;ENhyOrY5ord?E0Sq(I%HH8pvBn_di{@!x_$;d$@?d`0W)@_=xpiajnESO~q zK157_V)Ajvs@|x_gH#V=B2|oGPOtKhKNYRy9BUWCLw96)6XAwmgIyCU^&T-W8g*^x zlV1P;8m+8K#1x|<bV;V(eVZoaAfR`C+x9T_{^noN7PWi+boQFB`mf~`Z9S_ zvrjuyza=1?82PCn!cbuR1xdO68XtKx3<&-J?oG=1A4#1{7pwoq@1(zLyAMo&{xDFn z@%T}J9S6mD^&ZYgo5D#!NK!~ZR5tzI`{PNwYTWZjl6w&~|4`3$0Q132xJU|LkRU`R zOi#Nq8TR>19c5ZX2B{Mz)q9{?$UD8u6@t{qNr_7Z2jMD1iB#dE1T_YA6QrzY;T8F?cN#F4@y1d^! zo8_H2R5+SdBiy9IxXA{MFjHP6#Zcfd`l<6GQz-}@z!4DA-1 z2(GlFMy78(Oc_2)^Z|a?V7J4kS(i(&Bl!A!n-v=Ef8nwKR;#qiTZd+s-nmimb_;#3!QLmGZupHMl zLbya!MThV)ao-DF0o2%Q^4qlzC6wr^TXD~kz@;R@Os)wzj4RwCVbbx2tL$|`N}j3x zNJgjK2-|PYCFzs=7!= zfYF(E8d#eYvOeBtUDrx8`5{^xYv1Q6Yzt_nR6!XU#n|J1H(RA;U?++hyNiVUIFQY6 zKUK^bPQvzPHcYR(7?y0C?=;iQ#PfI%i7+`3oW*xuY} zrE$9W!(WxPo<)Y&>;7RUk-o0m^O?=6>%w3g82R>rx8*{Lo965-AVqe*J3X{Sa+#S+ zq6DF6@Ub4lA=UVmAFSvjc}66U^IZXR^uz_Z1vbm!-dmHohO*Lzx8-`hydM;R9t__L#NRt@^kV0o`4 zk*(?Phe))~@^{k-i1VIdI`GNVgcO5^Glv8$SAa+&QacNcF(R%QWF}(vJzt^$n07DH zEi?etV((vjOO2(sZ>kSiVn9x&35F^toKY~Zh^g1o-N}SANve5}c}na{yM6)ho*T=R zu#@}+-xP63;ItXkH~dd3FHth&Zrif)swt!&0mK1kMyFnnWVOZb_h?^h+y&UjuIN&Q zHi+I9scnSZT5B!EG$lqgi6fwH()Ls=68GDg?*_1E7E6cDZyvuZe6YOE(zSi4)ll}| z%bGd!y${0;x!m?hr1RdPXvzaNX<(WQxU@M-8Le<_!t9|}uc5LCF~HqYjL(dY1A#6^ z+n%zup?AqV)*6KeshE2!D)x;|Ce>W~d42Z2V~@T6kWDa(S{|>+r&Iu5Ruv_GR~t3= zJ0CH%ro7;vU>w>r>bbH+Kz{xqW98tFVqU=U|uH-!HAayNAdmN$rO@PpU!LC0@Oa%a0a&V=9}65ZtZJ?8ALd>6HVw?TL_& z7rqVPSJZ^0PNdN~wvl;P89q+#vwd-v4LXh8nl-`55g<(}7CJ&T6}`uDh{qkbY&9*x zxXA;YG|t5{U|s=2R668``p_Y_L0$`(2rX5vGUHc8%zxJ-Y-S~EYKSx_({3rPF6O)4 z2;PkcrzzPyKbM;7=Q$yV+jlMK{YOuw-!$D5$sR4Vc_%Yuu9QaQ}9{Z;as9{OgEYBQyGkf3C{goPUixYcR)) z*u-YlB9h$W&mD`W^dp|KwvcyA@_dF*>J-W=2c3-S1 zVBYo;3~a6>r2llB*}mvfjhQGJVHQJD)K68JdFRbP-uvLT>oXXI=qD>RH5bV{y~L9o z=XRb0JRx>lJUN`&?rx7<`zPOBY}i7fsmQ}4+Xh_RVIY~o>j<{Cm`JGubPfdE%<-)t zT_~@gk8T_qLcoQ)hKcZ_Kkt%clwv`=c~aka>>iAI`s)-i4T@6Q-8SMw8@;v%J5Orf z&bmHulcAgd=FdPqpcn_6lS@X{iz6D=jIaPPc}wLwb(vs$h#W6mhIpgC(bf6wbg zJP8u7(n)u}QVE$cSPfa;6lvUOWyA9Ch+ZFUl+_eFWc~HoZCU>k6s#PPL?f&ij2Ie! z;eO)f@4VG_vM%kLR!hF)<#s;k>_9}0-?zPSA$|C+CFdJvej9g645;96w;8Lqf@-g4 zW+gS`rb|{=*rw_}!Gsn0=fUcJ&2oVwgjn>#8rY(EQ*{{-T7*O%`A58+aK03mt)BOD z4z&?3KlTiN%M3a_EEyiFz;uUpSP(w2MM-R&N7qEMiw5WdUh%TU#3rn~^+d}^bZ$hDy~^<=l@IcBqGvG4A0d_)bVr>lAK*s6&$m(D%{Q^wN(tS<=ZPLjO{ zEv5b>#5Ow?E>-5W)ukl5g)ZQhCBSp@N@e2A`3nr_(j)Bsa+0fv*}76=m1+*|YQVuY)glKe2_R%Sft_k}YU|Cj}ffJyld<`#(vi&!#P}8~6O$ z2QZRDW#Y|lo9P2eBu<7aq69X-+0;BIZSxOaoh4?1Vjv8U8aHiy2VH$djd%2Ly9{Al zfqKRyffrgIH6?S~@A@aI2Sc1ZW4;Y#qWK3UZoAcrPX{uG{%ItBWdBiIw*c8HbzK@Z zsp%#)<@+urBg6EO+3y_|8rUvwYX61RiPzoJ(XDv}%=wO$`<~$1cu=WpO`~VB%LCx$ zg3gtuff%LwGJEk{J0v$mbbT_%%}nHxEq12Oak*p{#;8-Z$gsrAu8z)d>5siQdLz=9 z_4fm-Epk>5rbsCwh->?X9%qjO_yVwW8 zSnmh59z4pHWnu&T*m^qp%!?E;T}ZBOsC?d4+y6BP@pe&sf|Gwk`|2%9Jdbf4S~%x# z5Vjm$fGOfq>nBw10_epgoxd{+xd34>m`plXFN733>F&q&Nzu~kXzIXFuNBRXdG|b7 z7B8gH5{(Fn>|2%?2EVU7K8|P*u_&!AL_0?>{qnTus zObTe^>turs(??@czP;2QUtHo6e2bwyV8xAK(~)U@lMAkM_~O{5jrIT4bzV_Td||tX zP(!au@6sWlNN>`l2}rNfL8JvxdY7gk7`hTcq)SJ72>}G8iPEbC0jbh^NOH#i_nmdF z&RpasYh~7CX7+ye`~04FH~n7PFP@DeYA}uxUZ4kmVqeTY}U!RqR<1JBam0 zAI3!li_Rh(Pe5F>JsI0lf#&{_0K@Pe;O$PkNAE?f&$m;d+58L~O-j4H^FzR(RSAqB zPj*(P^j9;vb2Enk?yvC|air0!lB0hwRCKb%>?;-;bke9TA8?gF57-p*AMW!N4wyQa zRbao_$u8HMIN5Lle^N7{YFW4Bm0P30m28u9rNpZ`t{n)9Dx)s`Ry87~)3|Oifaji)!Xyl9)jEkd?QlPja#l`1dUb`# zwEby*=#ofaFaz;8jxDty=`;>deiFA%MKd=EK?rrv6@H2IqAev!tMv|3!lomJ3-0;G zAn|>XJk(xKdpL;89~=JU!BGj<1u0_btXhLB@&qPiKdn{V{`GcJyi@b#qntAP=atVN z|Hk7XI*39#XRaYCClPDXUoChCJy(vT5?UZU`h3XiZbf~SgtqXFXIT%8rou0`wXa%K zIQV=!Pb$`OY7Z89!fP_)B|Th|Y>3e-PEvE=Yj16=np~Otu+sfh+yeIEg9`K7&C5vERCJfFPfa7)JUAYfxXzcQZ+v1CKRT z>$RrCF$eBsucPALsR5S644J_F?Q*Q+`c$L$evP(jSN&3VQ+w~AQYeHJ=$+j4>83|A zScr}_b`H0At%{-Ywls#}bsxqScBSnJ;WjTww#L$F04v_+!4bt37bWos&`SZ>BwuSSCz#@nB94YC_A2G|Sg$*9L)g@Nf*YX&ml1=`kcq$hEivlA=1@0nMf&CuLkVUKDH#w1 zbD7GC<*~Cq{5~1_1M|Sw-9dQOM9}Zu1yns*{19|LrU3X4GGTgP$I%<$|iGffin?f$%N6!mt5xuQL@^;4s23ht&t-u zVi(F4FR^yiauAbVMnMX_Gt%%mJKU0p@6aJcYukoAYW{*yZd;KNHB)UdSftKU^|8<| z3^i;MdYc8eA)}lbb>08un%b$#$f7>!Jq>tqF8~gYxcYF-)OZJ^99w=qI1-S2!vCO= zTl#eMrz(Y%XvRUn`uufvoB&;&A1y0mVms@dt_;@mq1#0-qQ5TkE5RJ}K~DjdKccQ| z8vE%b;`hPH9@m`|;+-tYu{8phKYJnZK|Bsw1P2U)*vt zYb=j2A!gPqK zBJK0pW%X6gU$=;#hk4|7o~&A2=W2fb)q1}%c_$GcQ1z9H&H@J05R>ca?+>?+>O)T4 zJcOOA{KL%2#9N#!2ZF6Ke4n-IbMASP@hoPHRD^!WFgktpvN)y$QGvR#{k+J(MC}K? zjx$33!Lu)BBG5}bp-9A#^%V?+J%d!pwRpbVwy3Sn@g02hn8(pTEQ#=D-*`)EKbQj# zPQtmlWd78caez@42!IEp$gn@?#ee!5f1Pf$pvGgB3{C&#)vBJDadt#HK$;m`JYki7 zgr*_vE{GcI3hl?or@L|v;5xs>Ma?wacN{!>uO_{NW4|`7Pnh_I^*n|i)y6@CAMETR z@Pfie?j!u385d$b;mLKrO6>Vfyk0RNPlj@M1-4eYGT8otI$ADHbdzlVBJQ>gd3A`T zYOBfttL685(`{u`jgef>m9P9$&Y90tm4lywT5kWSnad5iP{+K$bY|gqI$3vv>jS8} z9)2xY0ha!voAwd4917S-=)y!>b$~+)dDD+xcOPF|{XMtUIr3A_#tT!#%MYeX&^)K* zP0C zWBWy~xE+W-{XAAu{qg63M@Ir2{5L7m1`*!mwN$4QrDcU36d562d(*9lhu&3^jJ@H? zJ~VwDSBJ1 zPqO1A;R3g5{Rw3u5HF)JP9}_BNo1h~Uy9#Z`YH6FzX;@qn$y}OTds6ZHktnDD%9Nr zpHr%{e%Y*+cjVjjnuFXiVr1?6(*l;lcmXe;$*R@kXGDJsXpPc)dWMk3Pww8V^~4ZF z$TdP@9Ej~8q@}b(R*p%pm^z<(jM?*x=g&-8Sn{Ekv6s9$IvQ%ux}!R9)B_k^{zq%N z^Xhi|5wSrFWpobN!Pm6|&zR!1A+i=52Dmf<%Y@@pS61KI2#dI(GhxOAip$mENPw9V zU-n0iIzJD0hP+$!IQ2fOI#c6ES;3sfKZfM6=)uK@LNFr>Ay~8w=FMwbFx$;N62_8x*0)OH2Yes1qb1Z8B^xs z!m9ig6huvOJ%Q?^R7rP&KgU~(?+#c!wdy;2<}ug(%tQ|{C9h~M7aiBTy~p%m(okJU ziV&r0PxV)w52_;FPfAGjXY87?A+qyfyZ2!|F+4~YupF1%#OP*5w!kK5oM(WvFw(3? z;j38F?{z<@XP4V5<8I`fD=4-!RK)&Dud$uO&1i{DCq`75&H1vz`N1=i@LS&nl4zxr zSak8}n+ZrRs|0NXqtkbDBoXJSd+zE?aioMY!2X`){Cn!wC!0i-_7)y6iAS&EBr{xr z-IXS)45muQC|OMS_(~*gjM}UdF!xdCeh&B!FDEscA?PgP`&ykUy{37+(TiME1}jvk z^BSVLLBMnN(;!OydU*nNA|?1?M3!}%Br>?E_p}VK_QL9X%c&{-9Bz}c)p^D=4tUt; z^Ib{`tTswzQwv*p)};|IQCT5fFCB1d$k&fy{IO9olL85tKjS zw$8&X{j?4ObD7nO9Bn3hiSYm)o4XO~2)|XVK4|lCXhB)@2pBc$ElT0Vgx|0096dp( z_FPr8u0$8wrff{KX(Y?}1>UG}y>^~xCg{RX2XA4?rru;F7K$eP10hLhp-9U&D%0qt zo==WDW0f%jn!h?4B-}AbDeol8Ur+D7VuD_o!$YATzHph@zz%F@0cU8kS+8V)pX|$W zuS3C?xDhgeU%uZJ2=@i_qWEJ@w0~`K>_zp;L*I#8|B&V%WFP_)s;Se_5f6%qQJ~eK zb%tb{&hZgCsEiDimKXKD6ose(#Y!Uy&=*RXLmpDJVE=P#dzuT@O2g#z3&RlJxhNEDtr|u(Cm-W84|q5@WsF?<5|Pmbj+?L)%M~* z)k86dX4hEhN0gi1*D&JmBckK6ixx|19@>j5L#vI-HyiD;SSh*7I90Y%SqV)w|CqO2 z+CCMJ=f-Jt=?J4o^vE`gMm7R#f#&FBaWih0c{0wK+PTtSdU+h*(19Q6@<|B;p+ZS*OBFb*hQa=uq#MGFLqO#a+&CLl%R+}$Y&zUcrSyB|$ zb)Fn(V2iwRKBik!)C&)4b38A4`|L)(KglZX43 z2xfbntGhWzpWGAd`VPa&FbG{|WNAOu=cZAsDQ|Hh`Qy&Ne^KXb(su@ULgt_r(cS9A zx6^Uy8lZ>E=59^Abi#^44{7B?E|G+#7p8>#>BkT9ZL=xQ+umy!)a6GZjk}Feo!-T_ zNEN?N^j^7Akl=s{;Qd#u1nu^s7-o|1_z^x<$0APGCS-*#kgepG(|38elU0XelssEI z(^2i&k5|%lh5;zE%WQiCIQCR<_p&Gi^SpI9dv8E!E^0f{^yk1 z;*GDrLQ!6$xDUJmnUj&;MEmrMvM2;4?-Rb%!d6aAPO_i^a$n!BEN83H>_3<`<>+&ib5|wzDnV2JxbNlP* zecGib6r7xZatr*sW;h;#7Bb_*yM+hL;1sP(fp{0MyxE|*g~N+B1LvXI^?J?+TOk~W zklWy)BvJ$;Peg-UefNUs~}%N+$}=v;k$lu1?EJspo3 zYL1YlMs5V>BCJsLrvII*L`5`W5aZdWt$xM7zndBNVe6Wm-JLH$9;$QCF zWljWh2w8I)d(`-6ok1G^SR?0-AARXP572pcdakl*Lqy7r=!X1XWMl%erwf2QMpYw5 z-x4q46(M^JcZth z(pt|B=|6T5oj0B>5R0{YGBm5z(RcG>@EdH#J-soL|jL$?h4=bRE=m^1P z0yH~52?m%g@8GK>L)mppj-B!5BK}}kmGucWU3U+vcAl*#A5#=81x)eafe2$0^d2xt zya6^d$)hK?%@LIKF7X?A1ffwqE$wf1VPph<3m?w3rU!qIbN(QzhSC|!)gO*M5v4nf zxuG=3kKVNsc4PMQ{u-GF{lKjJt4DC~w@E!^D~H&t&5Ui&4F}HQ{{3!m3TSuMYZxS} zdPL?%|MeY6C2l|00)`Mm4-{kORKx~kP6gg`Mk=>Jqb|oWwz} z)FLhW=ADXzJ^cC|V$p8_sm;05y_<)-IddjVhU&u{XvttsJ+u^Bc$6;*99d**Q;y;c z8Q?%9P@Kp<(h<~SsfnkB`@_Rc4~w3T`=niNA>eAVT6|W}sw039JsMsE3xytgHuTZ! z(8*F0h%cT#MsN3?>FL>qX|(9+qcaJCd4|pm*VrS;`~;DGOxKHb*R)i~)P;91$++Q4 zVon+|H+v&*-B2d+kSHhY_PgG?Sq+%(BV{3}&NKYnuD8WZoDuzcA?unNgKWR~l zD8!b~lG3)YEaYmH1C(^ai(%+v!LQ2T7UxoB+u_ zlifNTl_;Lq*BLo3D%DQa zr;tk0I$(B^yBoU4P+`IIU`pqkK&W0%#^bHxp2Ky=LOEh(WxO1BBtjmF0nAi`C20=Z zGQbl8+RtovQ&J@X_)B`PvN?;mibyLP(71P}PYSB+dLFoMX{jN6g$587cisKRqOYBR}b&eT){fz;GThu$-N7Z8G{ z5e0pc;7<|m*$~LnX08chf{PQM5615r0jD{>4p{!Qs_I0|?^j3N1VRIj%^>LFRSESZ zGDP#@9y;%zC}}}iWF!hveA4D+3g&pk!_`@We&kD}ct9im&2` zjsq1|3lmnPYcr9<>H^$}IHG9}b&lZ18we3%&cvUW98b5(Ef z>Q3}-;VSYiqpbnyp7R~lU0$I=4%;V!SghXCMRvHFLw8F1*Pd-L*IX>E7Bq>Zr=NlR zXKW7*CC8g;hMI>=@S60?;f-d9CRd~58zUl^L_|#ryNcOPmNpIi>6`3~FK!;v0INf)=s2`6K`Wd|_As$$8&pRvoq~GHA;zRi-`69=!rMASv*#%U z&99fzLJms5+aNkROJ1~JO4D3Gs76m`Yd>uWxA1#E1}>aNz8GR!_sz7@vkb4f^BgT{ zn`rEJvUXP_=5ZjSqkTi%NP{C`!rnJEiFFrE7C*d&MBug<@=evwiamqJc{Adof3Ns| zPJ9x9pUnl!=BL(^lbbGtBlIVOw2aEx;u(p5Fp!Y602C`gVtppMa@=NB`1_Cxx$r?7 z$X)TK_2V5y$`BjS@O~iLmE=}Fym;Kbh!6o1O`|J`j&Lw-#8Wo+ihHv*oIAMX>{P6F)f(+ACsAu~NASyCRHx`OripVb|&9q$!rf1bDXrK4t3V{uydEKpV6QfWJ z4-MV|0Kw4dy8zeZXXMy1=dNcr2WDtd8-#9@G>Pk%(GM-!K*e$|ym`tK8(Y!<{n^m# ze%fCpN3OOQR(&1$ojSR=o*Vm_tXb!5Ey%=eIO%7G%lD=D1?nP7TbuG7#b-+l?hD5cTce%7w~gsKToLy&JC{oCO{t@-?F=Hh>+f&*thG*D78RvF&6__}J>^WFW zvj`k~iCG_v+83N%zRC?rxl1_k&%J0~#A&>fb4P?}*YDSfm)Q%I*#%c-Jelt#(p#@3 z`M~3DADKg64*O8co&Z$7_kLC+R#~;b@iO7$?)`zGTkIAzk1KO-V$R(yjHWr0kR*9vln zx#TYH(=Gp%>j0Pb?$bG_K$K60tY~B->7E6k&2JU!%c>BZ3jss=@d!QvPb|&71|f&+ zcP1kYi4Ve>UMCaU3Z(%fnO%~$;JF%&a*gQ}&Vv>@aHnMm5~Qeh-F=hYp8lk~Mj~ej zU@3TUXS2MG!Kx8Z(Y-7%?4r^8(ST&2IRwnVyw?_xVV{15AI>kO`m z!>+F>ubHZ}*=A2d#V8UwF|UCBof`axd3Th=JJcgT@5tOFOB%SvOG9sh(S5b1oa{ol zAb@swJk9Z4vUL0jrcQUFaQDi;To^4Awac>{W@~dfhQ2Mr)V+dXYP?zi-9^omYVU)0X?c zE#m*|te}mH@s+dZ3S%8kl|R$HswOk0;a=+wI6lW=7xFkq{@K{rfJ6g-$z;MFy09Xu zz#!$zD)@`-zy8tfJIjqfDMu0Q?9kDxiL;c-4+mLe<`2f(b`EL?WXyTVJTkkE2NJKz z6#O+cn6p>W=bW~!-l+LL!>&(+QxC4QiM{-nMVFsIx;VUSIz3Kq@1Sqn7J>kyG5UzU zj41V`<-)Vs8vpG_)bjS13l2cpzrlTz!~cMHe8e|US(oFntHPjV_)JnH=O8dHX`46~ zJqP?Nxj&Gz^b6Iyyx@NM(27 zw{F6vrkbBh0%P|TBJA-i{Kj!F3%;d`EplrLF{_>BSV4}(tKyNZ2(Nvlr?4Svj5@zt*`@ zPZt}=A-U6m@`a&VXVd~fvX81K;P`NX$C_)OC@m;ukpMeeo*Y1#$?bi{MQZ$W;(v)U zyZJ^OmQanVub`K%dc}6lrvuAx`!G7Xa@A`?C!Jrl3DUt29C#lZPP8x@)dYM@ZqPAt zACCI_+{Mog9lYiT5_S*n`NobR>E*!CgH`e|b!uAmY9E3Kh-DPxlLb$%p(1o6G$=dhsk?!!EUC=H`FijxW8abpt$VLfZK}{7z(Q z#v}ymiy5>~4BPF4yuftXu+Z~I9V8L@8iGbeze`@AC14VJnDLE=x|!i}PT@zv7eRYw zJsfYt!c;hK#LBdrQbwxz+M49o#3^`Nj;n=v@PV{rb{%8o%vKpeouA|@_QezVdCcLL z6bG++UJhR;2~Tc`!#Mvy#C@JJJmj;Dvfx~n4tud*A%k{ot9 zbqGLX12uYeAM&ASHS7|J4A^^jmeCa!r^J2uzb08~UMOOnw!@D%z7H5SC~$L(v1jZ!IH?()h)|_tQAxxh@4kn zY~2by+m#`_R#G_2#H1-3Viwi&Bag;4vJ zTCYoT!O3`~5drIh6ZuDg_wK0LiKDE1Vsv zL>0~6A2PxxKQB8zuRzQ`BCeYso>srFoa&|tR(T8}GSow%+qVPG0>%aMgEIC4*5w)s zjxo_Sx3>npmB{IV%>O-u+5~``&p=+(`DK(2jb|~11R^D{LO|Yeq}t9p?>1P1kX4at zGm1Oi{g6HHU_ifovVf!l72~kioqo0$0O>9PjY2UidfC-eX!6oX6&scBiDu;EH$3=x z)b;BtmE(G$?n>FSj+SN)K<9{Ue@rgdS27OA@IaK!d%!caFp%9O#w<>3?DId+;iq#5 zhM%-_JcsF-(hP)AD8le0*QXta8|OoL%T_q{6pZZcitN13ExTvWc;5$~{_t(Z)EzwD z{H7!P7VWEvilC+;9X#*+MMGU@kq};9AR1#CT}#7KCd?gcMzQp%$JeC0peU{XFWDsp z7mYMJ-<*^l9IQcaXtET1K_7GA*vj}4LrY&aiYoXQyZdF{;5n(5X&*asLz~OLBe1oN6)f~)r}XJsZ;&H^nu*>dG*CT$a8eM}QSeKD z>s6eD`rCf8UTHL2*$OSK8|iiT)#BsOjM5dZhQm+gg$Et1bp5n?Xtt1Mc-XYk%p$#G z!gCs7OR$bJds>HO`$cPNcQydbX(w05BNn-Wxu*(0kEhE2B~!`|_;+poo&r4h=j$ix zr)EwqUuvdXh@Nmt+lsd#a(b1Os2(i7B!QM2?>Ki&2ksa7OV`3;D&A$<&ddUfu2N^r-#rzPrdl;|XAo z&$+vI_jigc9&zb=C1g=0b@q~%@KA_w8=i6&+o#6mXsrg4m_zGyQCG1!0)@-xy??W2 zSEezGe@8t}>G|mSACp+pPT+me$i!lJ$YG*Ls_+j4|?|ErxT~!u4@sH`qtn(qX^bdP3W< zhZ*A2xNEs`bo}wy)~lGc70jh4CQzqww`UnL@o5xNTE|J?tFl*o+$Wr@qO!M*eDV@N zse)Lan|LI4;fQc9OvBs$*JcY3y=F8*<|h4qHeKxcZO?xy5jhq4#C_}V{mw~Er%mbA zxzzt8jc2}V#JZfjLR7-C1Gy~*MT^cVKp++jVNc*8Wm~^ zz#oA1Qw&v>E9v=b4aft7-DtEV@z;-}y(ww;o~FLU7=Simbh9n~)r_y>;Qt-Q^@LOD ztDQEWb0O_E^ZT&6=EyGd`;WAU{wE3SFZ=*V9v2@Q&vXFcXD1%VYg>#!_UugUB$dp4 z+RN`G77}HF-_T{=eVa}(xdGBDK>_~H0NcD+q(%)jq@h@7DZ|^QeTl2xqrE=aT>Xm& O96Fi?8Z~MTvHu6Rs=w?2 literal 0 HcmV?d00001 diff --git a/img/crawl_file_listing.png b/img/crawl_file_listing.png new file mode 100644 index 0000000000000000000000000000000000000000..46af2cd1e1a983af748ced4f4ae3658507acb65e GIT binary patch literal 103555 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 u9}GN2n7hp*wgqiq00K`}KbLh*2~7Yh8HPy! literal 0 HcmV?d00001 From 1fdaf172a5e9ed0b92b96a98988d2e7c32549cb5 Mon Sep 17 00:00:00 2001 From: Laurie Burchell Date: Fri, 6 Jun 2025 10:35:30 +0100 Subject: [PATCH 2/4] docs: finished rewrite of ww tour --- README.md | 550 ++++++++++++++++++++++---------------------------- README_LVB.md | 358 -------------------------------- 2 files changed, 240 insertions(+), 668 deletions(-) delete mode 100644 README_LVB.md diff --git a/README.md b/README.md index 64da61e..8cd3c40 100644 --- a/README.md +++ b/README.md @@ -1,117 +1,106 @@ # Whirlwind Tour of Common Crawl's Datasets using Python -Common Crawl's data storage is complicated. We use the archiving -community's standard WARC format to store crawled webpages. We use -this same format to store text extractions (WET) and metadata (WAT) -data. +The Common Crawl corpus contains petabytes of crawl data, including raw web page data, metadata extracts, and text extracts. Common Crawl's data storage is a little complicated, as you might expect for such a large and rich dataset. We make our crawl data available in a variety of formats (WARC, WET, WAT) and we also have two index files of the crawled webpages: CDXJ and columnar. -We have 2 indexes of the crawled webpages, one stored as a flat file -(cdxj) and one stored in the parquet file format, which we call the -columnar index. +The goal of this whirlwind tour is to show you how a single webpage appears in all of these different places. That webpage is [https://an.wikipedia.org/wiki/Escopete](https://an.wikipedia.org/wiki/Escopete), which we crawled on the date 2024-05-18T01:58:10Z. On the way, we'll also explore the file formats we use and learn about some useful tools for interacting with our data! -Finally, we have a web graph by host and domains. It is not currently -demonstrated in this tour. - -## Goal of this tour - -The goal of this whirlwind tour is to show you how a single webpage -appears in all of these different places. It uses python-based tools -such as [warcio](https://github.com/webrecorder/warcio), -[cdxj-indexer](https://github.com/webrecorder/cdxj-indexer), +In the Whirlwind Tour, we will: +1) explore the WARC, WET and WAT file formats used to store Common Crawl's data. +2) play with some useful Python packages for interacting with the data: [warcio](https://github.com/webrecorder/warcio), [cdxj-indexer](https://github.com/webrecorder/cdxj-indexer), [cdx_toolkit](https://github.com/cocrawler/cdx_toolkit), and [duckdb](https://duckdb.org/). +3) learn about how the data is compressed to allow random access. +4) use the CDXJ index and the columnar index to access the data we want. -That webpage is [https://an.wikipedia.org/wiki/Escopete](https://an.wikipedia.org/wiki/Escopete), -which we crawled on the date 2024-05-18T01:58:10Z. +**Prerequisites:** To get the most out of this tour, you should be comfortable with Python3, running commands on the command line, and basic SQL. Some knowledge of HTTP requests and HTML is also helpful but not essential. We assume you have [make](https://www.gnu.org/software/make/) and [virtualenv](https://pypi.org/project/virtualenv/) installed. -What you need to run this? A recent version of Python. Most of the -commands in this tour are in a Makefile, so it would be nice if you -had "make" on your system. +We use a [Makefile](https://makefiletutorial.com) to provide many of the commands needed to run this tutorial. To see what commands are being run, open the `Makefile` and find the relevant target: e.g. `make install` runs `pip install -r requirements.txt`. -Ready? Here we go! +Let's get started! -## Look at the example files in an editor +## Task 0: Set-up -WARC files are a container that holds files, similar to zip and tar files. -Open up `whirlwind.warc` in your favorite text editor. This is the uncompressed -version of the file -- normally we always work with these files while they -are compressed. +This tutorial was written on Linux and MacOS. We think it should also work on Windows WSL, but raise an issue if you encounter problems. -You'll see 4 records total, each with a set of warc headers -- -metadata related to that particular record. +### Clone the repository and create a local Python environment -First is a warcinfo -record. Every warc has that at the start. Then there are 3 records -related to fetching a single webpage: the request to the webserver, -with its http headers; the response from the webserver, with its http -headers followed by the html; and finally a metadata record related to -that response. +First, [clone this repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) to create a local copy, then navigate to the `whirlwind-python` directory on your computer. -Now let's look at `whirlwind.warc.wet` -- which is in WARC format, but -the thing stored in the record is the extracted text from the html. -There's a warcinfo record at the start, and then just one record -relating to the webpage. It's a "conversion" record: it does not -have any http headers, it's just the extracted text. +In general, it's a good idea to set up separate virtual environments (venvs) for Python projects. This lets you install packages without changing either the system Python environment or any of your other Python projects. -Finally, open up `whirlwind.warc.wat` -- also in WARC format. This file -contains a metadata record for each response in the warc. The metadata -is stored as json. You might want to feed this json into a -pretty-printer to read it more easily. For example, you can save just -the json into a file and use `python -m json.tool FILENAME` to -pretty-print it. +If you already have your own favorite venv scheme, you can skip this step (we used the [Pycharm IDE](https://www.jetbrains.com/pycharm) to manage environment creation). Otherwise, you can create a venv on the command line by running: -Now that we've looked at the uncompressed versions of these files, -the rest of the tour will focus on the usual software tools used -to manipulate these files. +```make venv``` -## Operating system compatibility +After you create this venv, you'll need to activate it: -This was written in Linux. We think it should run on Windows WSL -and in MacOS. +```source ~/venv/whirlwind/bin/activate``` -On a Mac, you'll need `make` (part of Xcode) and `awscli`, perhaps -installed with `brew install awscli`. You'll also need virtualenv, -`brew install virtualenv`. +On many systems, you will now see the name of the venv in parentheses before the command prompt. You'll need to activate the environment again if you log out and log in again. -## Set up a virtual environment +Next, let's install the necessary software for this tour: -It's a good idea to set up completely separate environments for Python -projects, where you can install things without either changing the -system Python environment, or any of your other Python projects. +```make install``` -If you already have your own favorite virtual environment scheme, you -can skip this step. But otherwise: +This command will print out a screen-full of output and install the Python packages in `requirements.txt` to your venv. -```make venv``` +### Install and configure AWS-CLI -After you create this venv, you'll need to activate it. Run this -command in your shell: +We will use the AWS Command Line Interface (CLI) later in the tour to access the data stored in Common Crawl's S3 bucket. Instructions on how to install the AWS-CLI and configure your account are available on the [AWS website](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). -```source ~/venv/whirlwind/bin/activate``` +## Task 1: Look at the crawl data -You'll need to run that command in the future if you log out and -log in again. +Common Crawl's website includes a [Get Started](https://commoncrawl.org/get-started) guide which summarises different ways to access the data and the file formats. We can use the dropdown menu to access the links for downloading crawls over HTTP(S): -## Install python packages +![crawl_dropdown.png](img/crawl_dropdown.png) -At this point you have a very minimal Python environment, so let's install -the necessary software for this tour. +If we click on `CC-MAIN-2024-22' in the dropdown, we are taken to a page listing the files contained in this crawl: -```make install``` +![crawl_file_listing.png](img/crawl_file_listing.png) -This command will print out a screen-full of output. +In this whirlwind tour, we're going to look first at the WARC, WET, and WAT files: the data types which store the crawl data. Later, we will look at the two index files and how these help us access the crawl data we want. -## Iterate over warc, wet, wat +(We also have a [web graph](https://commoncrawl.org/web-graphs) by host and domains, but it is not currently demonstrated in this tour.) -Now you have some tools, let's look at the compressed versions of -these files. We'll use a small python program which uses the `warcio` -package to iterate over these files. First look at the code: +### WARC -```cat warcio-iterator.py``` +[WARC files](https://iipc.github.io/warc-specifications/specifications/warc-format/warc-1.0/) are a container that holds files, similar to zip and tar files. It's the standard data format used by archiving +community and we use it to store raw crawl data. As you can see in the file listing above, our WARC files are very large even when compressed! Luckily, we have a much smaller example to look at. -And you will see: +Open `whirlwind.warc` in your favorite text editor. Note that this is an uncompressed version of the file; normally we always work with these files while they are compressed. This is the WARC corresponding to the single webpage we mentioned in the introduction. -``` +You'll see four records total, with the start of each record marked with the header `WARC/1.0` followed by metadata related to that particular record. The `WARC-Type` field tells you the type of each record. In our WARC file, we have: +1) a `warcinfo` record. Every WARC has that at the start. +2) the `request` to the webserver, with its HTTP headers. +3) the `response` from the webserver, with its HTTP headers followed by the html. +4) a `metadata` record related to the HTTP response. + +### WET + +WET (WARC Encapsulated Text) files only contain the body text of web pages extracted from the HTML and exclude any HTML code, images, or other media. This makes them useful for text analysis and natural language processing (NLP) tasks. + +Open `whirlwind.warc.wet`: this is the WET derived from our original WARC. We can see that it's still in WARC format with two records: +1) a `warcinfo` record. +2) a `conversion` record: the extracted text with the HTTP headers removed. + +### WAT + +WAT (Web ARChive Timestamp) files contain metadata associated with the crawled web pages (e.g. parsed data from the HTTP response headers, links extracted from HTML pages, server response codes etc.). They are useful for analysis that requires understanding the structure of the web. + +Open `whirlwind.warc.wat`: this is the WAT derived from our original WARC. Like the WET file, it's also in WARC format. This file contains a metadata record for each response in the WARC. The metadata is stored as json. You might want to feed this json into a pretty-printer to read it more easily. For example, you can save just the json into a file and use `python -m json.tool FILENAME` to pretty-print it. + +Now that we've looked at the uncompressed versions of these files to understand their structure, we'll be interacting with compressed WARC, WET, and WAT files for the rest of this tour. This is the usual way we manipulate this data with software tools due to the size of the files. + +## Task 2: Iterate over WARC, WET, and WAT files + +The [warcio](https://github.com/webrecorder/warcio) Python library lets us read and write WARC files programmatically. + +Let's use it to iterate over our WARC, WET, and WAT files and print out the record types we looked at before. First, look at the code in `warcio-iterator.py`: + +
+ Click to view code + +```python '''Generic example iterator, similar to what's in the warcio README.''' import sys @@ -125,12 +114,18 @@ for file in sys.argv[1:]: if record.rec_type in {'request', 'response', 'conversion', 'metadata'}: print(' ', 'WARC-Target-URI', record.rec_headers.get_header('WARC-Target-URI')) ``` +
+ +The `ArchiveIterator` reads the WARC content in a single pass and allows us to access the attributes of each record (e.g. the record type through `record.rec_type`). -Now run: +Now run: -```make iterate``` +`make iterate` -You should see something like: +This will run `warcio-iterator.py` on `whirlwind.warc.gz`, `whirlwind.warc.wet.gz`, and `whirlwind.warc.wat.gz` in turn. You should see output like the following: + +
+ Click to view output ``` iterating over all of the local warcs: @@ -157,24 +152,29 @@ python ./warcio-iterator.py whirlwind.warc.wat.gz WARC-Type: metadata WARC-Target-URI https://an.wikipedia.org/wiki/Escopete ``` +
+ +The output has three sections, one each for the WARC, WET, and WAT. For each one, it prints the record types we saw before, plus the `WARC-Target-URI` for those record types that have it. + +## Task 3: Index the WARC, WET, and WAT -The output has 3 sections, one each for the warc, wet, and wat. It prints -the record types; you've seen these before. And for the record types -that have an Target-URI as part of their warc headers, it prints that URI. +The example WARC files we've been using are tiny and easy to work with. The real WARC files are around a gigabyte in size and contain about 30,000 webpages each. What's more, we have around 24 million of these files! To read all of them, we could iterate, but what if we wanted random access so we could read just one particular record? We do that with an index. -## Index warc, wet, and wat +We have two versions of the index: the CDX index and the columnar index. The CDX index is useful for looking up single pages, whereas the columnar index is better suited to analytical and bulk queries. We'll look at both in this tour, starting with the CDX index. -These example warc files are tiny and easy to work with. Our real warc -files are around a gigabyte in size, and have about 30,000 webpages in -them. And we have around 24 million of these files. If we'd like to -read all of them, we could iterate, but what if we wanted random -access, to just read this one record? We do that with an index. We -have two of them. +### CDX(J) index -Let's start with the cdxj index. +The CDX index files are sorted plain-text files, with each line containing information about a single capture in the WARC. Technically, Common Crawl uses CDXJ index files since the information about each capture is formatted as JSON. We'll use CDX and CDXJ interchangeably in this tour for legacy reasons :) + +We can create our own CDXJ index from the local WARCs by running: ```make cdxj``` +This uses the [cdxj-indexer](https://github.com/webrecorder/cdxj-indexer) library to generate CDXJ index files for our WARC files by running the code below: + +
+ Click to view code + ``` creating *.cdxj index files from the local warcs cdxj-indexer whirlwind.warc.gz > whirlwind.warc.cdxj @@ -182,51 +182,31 @@ cdxj-indexer --records conversion whirlwind.warc.wet.gz > whirlwind.warc.wet.cdx cdxj-indexer whirlwind.warc.wat.gz > whirlwind.warc.wat.cdxj ``` -Now look at the `.cdxj` files with `cat whirlwind*.cdxj`. You'll see -that each file has one entry in the index. The warc only has the -response record indexed -- by default cdxj-indexer guesses that you -won't ever want to random-access the request or metadata. wet and wat -have the conversion and metadata records indexed. - -(Note: CCF doesn't publish a wet or wat index, just warc.) +
-For each of these records, there's one text line in the index -- yes, -it's a flat file! It starts with a string like -`org,wikipedia,an)/wiki/escopete 20240518015810` followed by a json -blob. +Now look at the `.cdxj` files with `cat whirlwind*.cdxj`. You'll see that each file has one entry in the index. The WARC only has the response record indexed, since by default cdxj-indexer guesses that you won't ever want to random-access the request or metadata. WET and WAT have the conversion and metadata records indexed (Common Crawl doesn't publish a WET or WAT index, just WARC). -The starting string is the primary key of the index. The first -thing is a [SURT](http://crawler.archive.org/articles/user_manual/glossary.html#surt) -(Sort-friendly URI Reordering Transform). The big integer -is a date, in ISO-8601 format with the delimiters removed. +For each of these records, there's one text line in the index - yes, it's a flat file! It starts with a string like `org,wikipedia,an)/wiki/escopete 20240518015810`, followed by a JSON blob. The starting string is the primary key of the index. The first thing is a [SURT](http://crawler.archive.org/articles/user_manual/glossary.html#surt) (Sort-friendly URI Reordering Transform). The big integer is a date, in ISO-8601 format with the delimiters removed. -What is the purpose of this funky format? It's done this way because -these flat files (300 gigabytes total per crawl) can be sorted on the -primary key using any out-of-core sort utility -- like the standard -Linux `sort`, or one of the Hadoop-based out-of-core sort functions. +What is the purpose of this funky format? It's done this way because these flat files (300 gigabytes total per crawl) can be sorted on the primary key using any out-of-core sort utility e.g. the standard Linux `sort`, or one of the Hadoop-based out-of-core sort functions. -The json blob has enough information to extract individual records -- -it says which warc file the record is in, and the offset and length of -the record. We'll use that in the next section. +The JSON blob has enough information to extract individual records: it says which warc file the record is in, and the offset and length of the record. We'll use that in the next section. -## Extract the raw content from local warc, wet, wat +## Task 4: Use the CDXJ index to extract raw content from the local WARC, WET, and WAT -You usually don't expect compressed files to be random access. -But there's a trick that makes that possible with many -compression schemes -- the trick is that each record needs to be -separately compressed. gzip supports this, but it's rarely used. warc -files are written in this unusual way. +Normally, compressed files aren't random access. However, the WARC files use a trick to make this possible, which is that every record needs to be separately compressed.The `gzip` compression utility supports this, but it's rarely used. -To extract one record from a warc file, all you need to know is the -filename and the offset into the file. If you're reading over the web, -then it really helps to know the exact length of the record. +To extract one record from a warc file, all you need to know is the filename and the offset into the file. If you're reading over the web, then it really helps to know the exact length of the record. Run: ```make extract``` to run a set of extractions from your local -`whirlwind.*.gz` files. +`whirlwind.*.gz` files with `warcio` using the code below: + +
+ Click to view code ``` creating extraction.* from local warcs, the offset numbers are from the cdxj index @@ -236,22 +216,102 @@ warcio extract --payload whirlwind.warc.wat.gz 443 > extraction.json hint: python -m json.tool extraction.json ``` +
+ The offset numbers in the Makefile are the same -ones as in the index. You can look at the 3 output files: -`extraction.html`, `extraction.txt`, and `extraction.json`. Again you -might want to pretty-print the json: `python -m json.tool extraction.json` +ones as in the index. Look at the three output files: `extraction.html`, `extraction.txt`, and `extraction.json` (pretty-print the json with `python -m json.tool extraction.json`). + +Notice that we extracted HTML from the WARC, text from WET, and JSON from the WAT (as shown in the different file extensions). This is because the payload in each file type is formatted differently! + +## Task 5: Wreck the WARC by compressing it wrong + +As mentioned earlier, WARC/WET/WAT files look like they're gzipped, but they're actually gzipped in a particular way that allows random access. This means that you can't `gunzip` and then `gzip` a warc without wrecking random access. This example: + +* creates a copy of one of the warc files in the repo +* uncompresses it +* recompresses it the wrong way +* runs `warcio-iterator` over it to show that it triggers an error +* recompresses it the right way using `warcio recompress` +* shows that this compressed file works + +Run + +```make wreck_the_warc``` + +and read through the output. You should get something like the output below: + +
+ Click to view output + +``` +we will break and then fix this warc +cp whirlwind.warc.gz testing.warc.gz +rm -f testing.warc +gunzip testing.warc.gz + +iterate over this uncompressed warc: works +python ./warcio-iterator.py testing.warc + WARC-Type: warcinfo + WARC-Type: request + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: response + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: metadata + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + +compress it the wrong way +gzip testing.warc + +iterating over this compressed warc fails +python ./warcio-iterator.py testing.warc.gz || /usr/bin/true + WARC-Type: warcinfo +Traceback (most recent call last): + File "/home/ccgreg/github/whirlwind-python/./warcio-iterator.py", line 9, in + for record in ArchiveIterator(stream): + File "/home/ccgreg/venv/whirlwind/lib/python3.10/site-packages/warcio/archiveiterator.py", line 112, in _iterate_records + self._raise_invalid_gzip_err() + File "/home/ccgreg/venv/whirlwind/lib/python3.10/site-packages/warcio/archiveiterator.py", line 153, in _raise_invalid_gzip_err + raise ArchiveLoadFailed(msg) +warcio.exceptions.ArchiveLoadFailed: + ERROR: non-chunked gzip file detected, gzip block continues + beyond single record. + + This file is probably not a multi-member gzip but a single gzip file. + + To allow seek, a gzipped WARC must have each record compressed into + a single gzip member and concatenated together. + + This file is likely still valid and can be fixed by running: + + warcio recompress + + +now let's do it the right way +gunzip testing.warc.gz +warcio recompress testing.warc testing.warc.gz +4 records read and recompressed to file: testing.warc.gz +No Errors Found! + +and now iterating works +python ./warcio-iterator.py testing.warc.gz + WARC-Type: warcinfo + WARC-Type: request + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: response + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete + WARC-Type: metadata + WARC-Target-URI https://an.wikipedia.org/wiki/Escopete +``` -## Use cdx_toolkit to query the full cdx index and download those captures from S3 +
-Some of our users only want to download a small subset of the crawl. -They want to run queries against an index, either the cdx index we -just talked about, or in the columnar index, which we'll talk about -later. +Make sure you compress WARCs the right way! -`cdx_toolkit` is client software that knows how to query the cdx index -across all of our crawls, and also can create warcs of just the records -you want. We will fetch the same record from wikipedia that we've been -using for this whirlwind tour: +## Task 6: Use cdx_toolkit to query the full CDX index and download those captures from AWS S3 + +Some of our users only want to download a small subset of the crawl. They want to run queries against an index, either the CDX index we just talked about, or in the columnar index, which we'll talk about later. + +The [cdx_toolkit](https://github.com/cocrawler/cdx_toolkit) is a set of tools for working with CDX indices of web crawls and archives. It knows how to query the CDX index across all of our crawls and also can create WARCs of just the records you want. We will fetch the same record from Wikipedia that we've been using for the whirlwind tour. Run @@ -259,6 +319,9 @@ Run The output looks like this: +
+ Click to view output + ``` look up this capture in the comoncrawl cdx index cdxt --cc --from 20240518015810 --to 20240518015810 iter an.wikipedia.org/wiki/Escopete @@ -280,57 +343,32 @@ python ./warcio-iterator.py TEST-000000.extracted.warc.gz WARC-Target-URI https://an.wikipedia.org/wiki/Escopete ``` -The command lines for these `cdxt` commands specifies the exact URL -we've been using all along, and the particular date of its -capture, 20240518015810. The output is a warc file -`TEST-000000.extracted.warc.gz`, with this one record plus a warcinfo -record explaining what this warc is. The Makefile target also runs -cdxj-indexer on this new warc, and iterates over it. +
-If you dig into cdx_toolkit's code, you'll find that it is using the -offset and length of the warc record, returned by the cdx index query, -to make a http byte range request to S3 to download this single warc -record. +We look up the capture using the `cdxt` commands by specifying the exact URL (`an.wikipedia.org/wiki/Escopete`) and the date of its capture (20240518015810). The output is the WARC file `TEST-000000.extracted.warc.gz` which contains a `warcinfo` record explaining what the WARC is, followed by the `response` record we requested. The Makefile target then runs `cdxj-indexer` on this new WARC to make a CDXJ index of it as in Task 3, and finally iterates over the WARC using `warcio-iterator.py` as in Task 2. -It is only downloading the response warc record, because our cdx index -only has the response records indexed. We might make wet and wat cdx -indexes public in the future. +If you dig into cdx_toolkit's code, you'll find that it is using the offset and length of the WARC record, as returned by the CDX index query, to make a HTTP byte range request to S3 to download the single WARC record we want. It only downloads the response WARC record because our CDX index only has the response records indexed. -## The columnar index +## Task 7: Find the right part of the columnar index -In addition to the cdx index, which is a little idiosyncratic compared -to your usual database, we also have a columnar database stored in -parquet files. This can be accessed by tools using SQL such as AWS -Athena and duckdb, and as tables in your favorite table packages -such as pandas, pyarrow, and polars. +Now let's look at the columnar index, the other kind of index that Common Crawl makes available. This index is stored in parquet files so you can access it using SQL-based tools like AWS Athena and duckdb as well as through tables in your favorite table packages such as pandas, pyarrow, and polars. -AWS Athena is a managed service that costs money -- usually a small -amount -- to use. It reads directly from our index in our s3 bucket. -[You can read about using it here.](https://commoncrawl.org/blog/index-to-warc-files-and-urls-in-columnar-format) +We could read the data directly from our index in our S3 bucket and analyse it in the cloud through AWS Athena. However, this is a managed service that costs money to use (though usually a small amount). [You can read about using it here.](https://commoncrawl.org/blog/index-to-warc-files-and-urls-in-columnar-format) This whirlwind tour will only use the free method of either fetching data from outside of AWS (which is kind of slow), or making a local copy of a single columnar index (300 gigabytes per monthly crawl), and then using that. -This whirlwind tour will only use the free method of either fetching -data from outside of AWS (which is kind of slow), or making a local -copy of a single columnar index (300 gigabytes per monthly crawl), and -then using that. +The columnar index is divided up into a separate index per crawl, which Athena or duckdb can stitch together. The cdx index is similarly divided up, but cdx_toolkit hides that detail from you. -The columnar index is divided up into a separate index per crawl, -which Athena or duckdb can stitch together. The cdx index is similarly -divided up, but cdx_toolkit hides that detail from you. +For the purposes of this whirlwind tour, we don't want to configure all the crawl indices because it would be slow. So let's start by figuring out which crawl was ongoing on the date 20240518015810, and then we'll work with just that one crawl. -For the purposes of this whirlwind tour, we don't want to configure -all of the crawl indexes, because it would be slow. So let's start by -figuring out which crawl was ongoing on the date 20240518015810, and -then we'll work with just that one crawl. +### Downloading collinfo.json -To find the crawl name, download the file `collinfo.json` from -[index.commoncrawl.org](https://index.commoncrawl.org). It includes the dates for the the start and end -of every crawl. - -Run +We're going to use the `collinfo.json` file to find out which crawl we want. This file includes the dates for the start and end of every crawl and is available through the Common Crawl website at [index.commoncrawl.org](https://index.commoncrawl.org). To download it, run: ```make download_collinfo``` -The output looks like: +The output should look like: + +
+ Click to view output ``` downloading collinfo.json so we can find out the crawl name @@ -340,54 +378,35 @@ curl -O https://index.commoncrawl.org/collinfo.json 100 30950 100 30950 0 0 75467 0 --:--:-- --:--:-- --:--:-- 75487 ``` +
+ The date of our test record is 20240518015810, which is -2024-05-18T01:58:10 if you add the delimiters back in. Looking at the -from/to values in `collinfo.json`, you can see that the crawl with this -date is CC-MAIN-2024-22. Knowing the crawl name allows us to access -the correct 1% of the index without having to read the metadata of the -other 99%. +2024-05-18T01:58:10 if you add the delimiters back in. We can scroll through the records in `collinfo.json` and look at the from/to values to find the right crawl: CC-MAIN-2024-22. Now we know the crawl name, we can access the correct fraction of the index without having to read the metadata of all the rest. -(`cdx_toolkit` hid this detail from you. AWS Athena is so fast that -you don't really need to tell it which crawl to look in if you have a -specific date. Someday we'll have a duckdb-based solution which also -hides this detail.) +## Task 8: Query using the columnar index + DuckDB from outside AWS -### What does the SQL look like? +A single crawl columnar index is around 300 gigabytes. If you don't have a lot of disk space, but you do have a lot of time, you can directly access the index stored on AWS S3. We're going to do just that, and then use [DuckDB](https://duckdb.org) to make an SQL query against the index to find our webpage. We'll be running the following query: -``` - select +```sql + SELECT * - from ccindex - where subset = 'warc' - and crawl = 'CC-MAIN-2024-22' - and url_host_tld = 'org' -- help the query optimizer - and url_host_registered_domain = 'wikipedia.org' -- ditto - and url = 'https://an.wikipedia.org/wiki/Escopete' + FROM ccindex + WHERE subset = 'warc' + AND crawl = 'CC-MAIN-2024-22' + AND url_host_tld = 'org' -- help the query optimizer + AND url_host_registered_domain = 'wikipedia.org' -- ditto + AND url = 'https://an.wikipedia.org/wiki/Escopete' ; ``` -### What does this demo script do? - -For all of these scripts, the code runs an SQL query which should -match the single response record for our favorite url and date. -The program also then writes that one record into a local Parquet -file, does a second query that returns that one record, and shows -the full contents of the record. - -To run this demo, you need to choose one of the following options -for where the index data will be. - -### Columnar Index + duckdb from outside AWS - -A single crawl columnar index is around 300 gigabytes. If you -don't have a lot of disk space and you do have a lot of time, -here's how you directly access the index stored on AWS S3. - Run ```make duck_cloudfront``` -The output is +On a machine with a 1 gigabit network connection and many cores, this should take about one minute total, and uses 8 cores. The output should look like: + +
+ Click to view output ``` warning! this might take 1-10 minutes @@ -467,114 +486,25 @@ equivalent to cdxj: org,wikipedia,an)/wiki/escopete 20240518015810 {"url": "https://an.wikipedia.org/wiki/Escopete", "mime": "text/html", "status": "200", "digest": "sha1:RY7PLBUFQNI2FFV5FTUQK72W6SNPXLQU", "length": "17423", "offset": "80610731", "filename": "crawl-data/CC-MAIN-2024-22/segments/1715971057216.39/warc/CC-MAIN-20240517233122-20240518023122-00000.warc.gz"} ``` +
-On a machine with a 1 gigabit network connection, and many cores, this takes 1 -minute total, and uses 8 cores. +The above command runs code in `duck.py`, which accesses the relevant part of the index for our crawl (CC-MAIN-2024-22) and then counts the number of records in that crawl (2709877975!). The code runs the SQL query we saw before which should match the single response record we want. -### Download a full crawl index + duckdb +The program then writes that one record into a local Parquet file, does a second query that returns that one record, and shows the full contents of the record. We can see that the complete row contains many columns containing different information associated with our record. Finally, it converts the row to the CDXJ format we saw before. -If you want to run many of these queries, -and you have a lot of disk space, you'll want to download -the 300 gigabyte index and query it repeatedly. +### Bonus: download a full crawl index and query with DuckDB -Run +If you want to run many of these queries, and you have a lot of disk space, you'll want to download the 300 gigabyte index and query it repeatedly. Run ```make duck_local_files``` If the files aren't already downloaded, this command will give you download instructions. -### Use a previously download copy of the columnar index - -And if you're using the Common Crawl Foundation development server, -we've already downloaded these files, and you can: - -Run - -```make duck_ccf_local_files``` - -## Wreck the warc - -As mentioned earlier, warc/wet/wat files look like they're gzipped, -but they're actually gzipped in a particularly funny way that allows -random access. This means that you can't gunzip and then gzip a warc -without wrecking random access. This example: - -* creates a copy of one of the warc files in the repo -* uncompresses it -* recompresses it the wrong way -* runs warcio-iterator over it to show that it triggers an error -* recompresses it the right way using `warcio recompress` -* shows that this compressed file works - -Run - -```make wreck_the_warc``` - -``` -we will break and then fix this warc -cp whirlwind.warc.gz testing.warc.gz -rm -f testing.warc -gunzip testing.warc.gz - -iterate over this uncompressed warc: works -python ./warcio-iterator.py testing.warc - WARC-Type: warcinfo - WARC-Type: request - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: response - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: metadata - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - -compress it the wrong way -gzip testing.warc - -iterating over this compressed warc fails -python ./warcio-iterator.py testing.warc.gz || /usr/bin/true - WARC-Type: warcinfo -Traceback (most recent call last): - File "/home/ccgreg/github/whirlwind-python/./warcio-iterator.py", line 9, in - for record in ArchiveIterator(stream): - File "/home/ccgreg/venv/whirlwind/lib/python3.10/site-packages/warcio/archiveiterator.py", line 112, in _iterate_records - self._raise_invalid_gzip_err() - File "/home/ccgreg/venv/whirlwind/lib/python3.10/site-packages/warcio/archiveiterator.py", line 153, in _raise_invalid_gzip_err - raise ArchiveLoadFailed(msg) -warcio.exceptions.ArchiveLoadFailed: - ERROR: non-chunked gzip file detected, gzip block continues - beyond single record. - - This file is probably not a multi-member gzip but a single gzip file. - - To allow seek, a gzipped WARC must have each record compressed into - a single gzip member and concatenated together. - - This file is likely still valid and can be fixed by running: - - warcio recompress - - - -now let's do it the right way -gunzip testing.warc.gz -warcio recompress testing.warc testing.warc.gz -4 records read and recompressed to file: testing.warc.gz -No Errors Found! - -and now iterating works -python ./warcio-iterator.py testing.warc.gz - WARC-Type: warcinfo - WARC-Type: request - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: response - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: metadata - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete -``` +(**Bonus bonus:** If you happen to be using the Common Crawl Foundation development server, we've already downloaded these files, and you can run ```make duck_ccf_local_files```.) -## Coda +All of these scripts run the same SQL query and should return the same record (written as a parquet file). -You have now finished this whirlwind tutorial. If anything -didn't work, or anything wasn't clear, please open an -issue in this repo. Thank you! +## Congratulations! +You have completed the Whirlwind Tour of Common Crawl's Datasets using Python! You should now understand different filetypes we have in our corpus and how to interact with Common Crawl's datasets using Python. To see what other people have done with our data, see the [Examples page](https://commoncrawl.org/examples) on our website. Why not join our Discord through the Community tab? diff --git a/README_LVB.md b/README_LVB.md deleted file mode 100644 index a145863..0000000 --- a/README_LVB.md +++ /dev/null @@ -1,358 +0,0 @@ -# Whirlwind Tour of Common Crawl's Datasets using Python - -TBD: (overview of common crawls datasets and what they can be used for) - -(tour is to get to know file formats, meet some of the Python tools for interacting with them, and to learn different ways to access the crawls) - -The goal of this whirlwind tour is to show you how a single webpage appears in all of these different places. That webpage is [https://an.wikipedia.org/wiki/Escopete](https://an.wikipedia.org/wiki/Escopete), which we crawled on the date 2024-05-18T01:58:10Z. - -TBD: check this all applies at the end - -In the Whirlwind Tour, we will: -1) explore the WARC, WET and WAT file formats used to store Common Crawl's data. -2) play with some useful Python packages for interacting with the data: [warcio](https://github.com/webrecorder/warcio), [cdxj-indexer](https://github.com/webrecorder/cdxj-indexer), -[cdx_toolkit](https://github.com/cocrawler/cdx_toolkit), -and [duckdb](https://duckdb.org/). -3) learn about how the data is compressed to allow random access. -4) use the CDXJ index and the columnar index to access the data we want. - -**Prerequisites:** To get the most out of this tour, you should be comfortable with Python3, running commands on the command line, and basic SQL. Some knowledge of HTTP requests and HTML is also helpful but not essential. We assume you have `make` and `virtualenv` installed. - -We use a [Makefile](https://makefiletutorial.com) to provide many of the commands needed to run this tutorial. To see what commands are being run, open the `Makefile` and find the relevant target: e.g. `make install` runs `pip install -r requirements.txt`. - -## Task 0: Set-up - -This tutorial was written on Linux and MacOS. We think it should also work on Windows WSL, but raise an issue if you encounter problems. - -### Clone the repository and create a local Python environment - -First, [clone this repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) to create a local copy, then navigate to the `whirlwind-python` directory on your computer. - -In general, it's a good idea to set up separate virtual environments (venvs) for Python projects. This lets you install packages without changing either the system Python environment or any of your other Python projects. - -If you already have your own favorite venv scheme, you can skip this step (we used the [Pycharm IDE](https://www.jetbrains.com/pycharm) to manage environment creation). Otherwise, you can create a venv on the command line by running: - -```make venv``` - -After you create this venv, you'll need to activate it: - -```source ~/venv/whirlwind/bin/activate``` - -On many systems, you will now see the name of the venv in parentheses before the command prompt. You'll need to activate the environment again if you log out and log in again. - -Next, let's install the necessary software for this tour: - -```make install``` - -This command will print out a screen-full of output and install the Python packages in `requirements.txt` to your venv. - -### Install and configure AWS-CLI - -We will use the AWS Command Line Interface (CLI) later in the tour to access the data stored in Common Crawl's S3 bucket. Instructions on how to install the AWS-CLI and configure your account are available on the [AWS website](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). - -## Task 1: Look at the crawl data - -Common Crawl's website includes a [Get Started](https://commoncrawl.org/get-started) guide which summarises different ways to access the data and the file formats. We can use the dropdown menu to access the links for downloading crawls over HTTP(S): - -![crawl_dropdown.png](img/crawl_dropdown.png) - -If we click on `CC-MAIN-2024-22' in the dropdown, we are taken to a page listing the files contained in this crawl: - -![crawl_file_listing.png](img/crawl_file_listing.png) - -In this whirlwind tour, we're going to look first at the WARC, WET, and WAT files: the data types which store the crawl data. Later, we will look at the two index files and how these help us access the crawl data we want. - -### WARC - -[WARC files](https://iipc.github.io/warc-specifications/specifications/warc-format/warc-1.0/) are a container that holds files, similar to zip and tar files. We use this data format to store raw crawl data. As you can see in the file listing above, it is very large even when compressed! Luckily, we have a much smaller example to look at. - -Open `whirlwind.warc` in your favorite text editor. Note that this is an uncompressed version of the file; normally we always work with these files while they are compressed. This is the WARC corresponding to the single webpage we mentioned in the introduction. - -You'll see four records total, with the start of each record marked with the header `WARC/1.0` followed by metadata related to that particular record. The `WARC-Type` field tells you the type of each record. In our WARC file, we have: -1) a `warcinfo` record. Every WARC has that at the start. -2) the `request` to the webserver, with its HTTP headers. -3) the `response` from the webserver, with its HTTP headers followed by the html. -4) a `metadata` record related to the HTTP response. - -### WET - -WET (WARC Encapsulated Text) files only contain the body text of web pages extracted from the HTML and exclude any HTML code, images, or other media. This makes them useful for text analysis and natural language processing (NLP) tasks. - -Open `whirlwind.warc.wet`: this is the WET derived from our original WARC. We can see that it's still in WARC format with two records: -1) a `warcinfo` record. -2) a `conversion` record: the HTTP headers have been removed leaving only the extracted text. - -### WAT - -WAT (Web ARChive Timestamp) files contain metadata associated with the crawled web pages (e.g. parsed data from the HTTP response headers, links extracted from HTML pages, server response codes etc.). They are useful for analysis that requires understanding the structure of the web. - -Open `whirlwind.warc.wat`: this is the WAT derived from our original WARC. Like the WET file, it's also in WARC format. This file contains a metadata record for each response in the WARC. The metadata is stored as json. You might want to feed this json into a pretty-printer to read it more easily. For example, you can save just the json into a file and use `python -m json.tool FILENAME` to pretty-print it. - -Now that we've looked at the uncompressed versions of these files to understand their structure, the rest of the tour will focus on the usual software tools used to manipulate the compressed versions of these files. - -## Task 2: Iterate over WARC, WET, and WAT files - -The [warcio](https://github.com/webrecorder/warcio) Python library lets us read and write WARC files programmatically. - -Let's use it to iterate over our WARC, WET, and WAT files and print out the record types we looked at before. First, look at the code in `warcio-iterator.py`: - -
- Click to view code - -```python -'''Generic example iterator, similar to what's in the warcio README.''' - -import sys - -from warcio.archiveiterator import ArchiveIterator - -for file in sys.argv[1:]: - with open(file, 'rb') as stream: - for record in ArchiveIterator(stream): - print(' ', 'WARC-Type:', record.rec_type) - if record.rec_type in {'request', 'response', 'conversion', 'metadata'}: - print(' ', 'WARC-Target-URI', record.rec_headers.get_header('WARC-Target-URI')) -``` -
- -The `ArchiveIterator` reads the WARC content in a single pass and allows us to access the attributes of each record (e.g. the record type through `record.rec_type`). - -Now run: - -`make iterate` - -This will run `warcio-iterator.py` on `whirlwind.warc.gz`, `whirlwind.warc.wet.gz`, and `whirlwind.warc.wat.gz` in turn. You should see output like the following: - -
- Click to view output - -``` -iterating over all of the local warcs: - -warc: -python ./warcio-iterator.py whirlwind.warc.gz - WARC-Type: warcinfo - WARC-Type: request - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: response - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: metadata - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - -wet: -python ./warcio-iterator.py whirlwind.warc.wet.gz - WARC-Type: warcinfo - WARC-Type: conversion - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - -wat: -python ./warcio-iterator.py whirlwind.warc.wat.gz - WARC-Type: warcinfo - WARC-Type: metadata - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete -``` -
- -The output has three sections, one each for the WARC, WET, and WAT. For each one, it prints the record types we saw before, plus the `WARC-Target-URI` for those record types that have it. - -## Task 3: Index the WARC, WET, and WAT - -The example WARC files we've been using are tiny and easy to work with. The real WARC files are around a gigabyte in size and contain about 30,000 webpages each. What's more, we have around 24 million of these files! To read all of them, we could iterate, but what if we wanted random access so we could read just one particular record? We do that with an index. - -We have two versions of the index: the CDX index and the columnar index. The CDX index is useful for looking up single pages, whereas the columnar index is better suited to analytical and bulk queries. We'll look at both in this tour, starting with the CDX index. - -### CDX(J) index - -The CDX index files are sorted plain-text files, with each line containing information about a single capture in the WARC. Technically, Common Crawl uses CDXJ index files since the information about each capture is formatted as JSON. - -We can create our own CDXJ index from the local WARCs by running: - -```make cdxj``` - -This uses the [cdxj-indexer](https://github.com/webrecorder/cdxj-indexer) library to generate CDXJ index files for our WARC files by running the code below: - -
- Click to view code - -``` -creating *.cdxj index files from the local warcs -cdxj-indexer whirlwind.warc.gz > whirlwind.warc.cdxj -cdxj-indexer --records conversion whirlwind.warc.wet.gz > whirlwind.warc.wet.cdxj -cdxj-indexer whirlwind.warc.wat.gz > whirlwind.warc.wat.cdxj -``` - -
- -Now look at the `.cdxj` files with `cat whirlwind*.cdxj`. You'll see -that each file has one entry in the index. The WARC only has the response record indexed, since by default cdxj-indexer guesses that you won't ever want to random-access the request or metadata. WET and WAT have the conversion and metadata records indexed. - -(Note: CCF doesn't publish a WET or WAT index, just WARC.) - -For each of these records, there's one text line in the index - yes, it's a flat file! It starts with a string like `org,wikipedia,an)/wiki/escopete 20240518015810`, followed by a JSON blob. - -The starting string is the primary key of the index. The first thing is a [SURT](http://crawler.archive.org/articles/user_manual/glossary.html#surt) (Sort-friendly URI Reordering Transform). The big integer is a date, in ISO-8601 format with the delimiters removed. - -What is the purpose of this funky format? It's done this way because these flat files (300 gigabytes total per crawl) can be sorted on the primary key using any out-of-core sort utility e.g. the standard Linux `sort`, or one of the Hadoop-based out-of-core sort functions. - -The JSON blob has enough information to extract individual records: it says which warc file the record is in, and the offset and length of -the record. We'll use that in the next section. - -## Task 4: Use the CDXJ index to extract raw content from the local WARC, WET, and WAT - -Normally, compressed files aren't random access. However, the WARC files use a trick to make this possible, which is that every record needs to be separately compressed.The `gzip`compression utility supports this, but it's rarely used. - -To extract one record from a warc file, all you need to know is the filename and the offset into the file. If you're reading over the web, then it really helps to know the exact length of the record. - -Run: - -```make extract``` - -to run a set of extractions from your local -`whirlwind.*.gz` files with `warcio` using the code below: - -
- Click to view code - -``` -creating extraction.* from local warcs, the offset numbers are from the cdxj index -warcio extract --payload whirlwind.warc.gz 1023 > extraction.html -warcio extract --payload whirlwind.warc.wet.gz 466 > extraction.txt -warcio extract --payload whirlwind.warc.wat.gz 443 > extraction.json -hint: python -m json.tool extraction.json -``` - -
- -The offset numbers in the Makefile are the same -ones as in the index. Look at the three output files: `extraction.html`, `extraction.txt`, and `extraction.json` (pretty-print the json with `python -m json.tool extraction.json`). - -Notice that we extracted HTML from the WARC, text from WET, and JSON from the WAT (as shown in the different file extensions). This is because the payload in each file type is formatted differently! - -## Task 5: Wreck the WARC by compressing it wrong - -As mentioned earlier, WARC/WET/WAT files look like they're gzipped, but they're actually gzipped in a particular way that allows random access. This means that you can't `gunzip` and then `gzip` a warc without wrecking random access. This example: - -* creates a copy of one of the warc files in the repo -* uncompresses it -* recompresses it the wrong way -* runs `warcio-iterator` over it to show that it triggers an error -* recompresses it the right way using `warcio recompress` -* shows that this compressed file works - -Run - -```make wreck_the_warc``` - -and read through the output. You should get something like the code below: - -
- Click to view code - -``` -we will break and then fix this warc -cp whirlwind.warc.gz testing.warc.gz -rm -f testing.warc -gunzip testing.warc.gz - -iterate over this uncompressed warc: works -python ./warcio-iterator.py testing.warc - WARC-Type: warcinfo - WARC-Type: request - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: response - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: metadata - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - -compress it the wrong way -gzip testing.warc - -iterating over this compressed warc fails -python ./warcio-iterator.py testing.warc.gz || /usr/bin/true - WARC-Type: warcinfo -Traceback (most recent call last): - File "/home/ccgreg/github/whirlwind-python/./warcio-iterator.py", line 9, in - for record in ArchiveIterator(stream): - File "/home/ccgreg/venv/whirlwind/lib/python3.10/site-packages/warcio/archiveiterator.py", line 112, in _iterate_records - self._raise_invalid_gzip_err() - File "/home/ccgreg/venv/whirlwind/lib/python3.10/site-packages/warcio/archiveiterator.py", line 153, in _raise_invalid_gzip_err - raise ArchiveLoadFailed(msg) -warcio.exceptions.ArchiveLoadFailed: - ERROR: non-chunked gzip file detected, gzip block continues - beyond single record. - - This file is probably not a multi-member gzip but a single gzip file. - - To allow seek, a gzipped WARC must have each record compressed into - a single gzip member and concatenated together. - - This file is likely still valid and can be fixed by running: - - warcio recompress - - -now let's do it the right way -gunzip testing.warc.gz -warcio recompress testing.warc testing.warc.gz -4 records read and recompressed to file: testing.warc.gz -No Errors Found! - -and now iterating works -python ./warcio-iterator.py testing.warc.gz - WARC-Type: warcinfo - WARC-Type: request - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: response - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete - WARC-Type: metadata - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete -``` - -
- -## Task 6: Use cdx_toolkit to query the full cdx index and download those captures from AWS S3 - -Some of our users only want to download a small subset of the crawl. They want to run queries against an index, either the CDX index we just talked about, or in the columnar index, which we'll talk about later. - -The [cdx_toolkit](https://github.com/cocrawler/cdx_toolkit) is a set of tools for working with CDX indices of web crawls and archives. It knows how to query the CDX index across all of our crawls and also can create WARCs of just the records you want. We will fetch the same record from Wikipedia that we've been using for the whirlwind tour. - -Run - -```make cdx_toolkit``` - -The output looks like this: - -
- Click to view output - -``` -look up this capture in the comoncrawl cdx index -cdxt --cc --from 20240518015810 --to 20240518015810 iter an.wikipedia.org/wiki/Escopete -status 200, timestamp 20240518015810, url https://an.wikipedia.org/wiki/Escopete - -extract the content from the commoncrawl s3 bucket -rm -f TEST-000000.extracted.warc.gz -cdxt --cc --from 20240518015810 --to 20240518015810 warc an.wikipedia.org/wiki/Escopete - -index this new warc -cdxj-indexer TEST-000000.extracted.warc.gz > TEST-000000.extracted.warc.cdxj -cat TEST-000000.extracted.warc.cdxj -org,wikipedia,an)/wiki/escopete 20240518015810 {"url": "https://an.wikipedia.org/wiki/Escopete", "mime": "text/html", "status": "200", "digest": "sha1:RY7PLBUFQNI2FFV5FTUQK72W6SNPXLQU", "length": "17455", "offset": "379", "filename": "TEST-000000.extracted.warc.gz"} - -iterate this new warc -python ./warcio-iterator.py TEST-000000.extracted.warc.gz - WARC-Type: warcinfo - WARC-Type: response - WARC-Target-URI https://an.wikipedia.org/wiki/Escopete -``` - -
- -We look up the capture using the `cdxt` commands by specifying the exact URL (`an.wikipedia.org/wiki/Escopete`) and the date of its capture (20240518015810). The output is the WARC file `TEST-000000.extracted.warc.gz` which contains a `warcinfo` record explaining what the WARC is, followed by the `response` record we requested. The Makefile target then runs `cdxj-indexer` on this new WARC to make a CDXJ index of it as in Task 3, and finally iterates over the WARC using `warcio-iterator.py` as in Task 2. - -If you dig into `cdx_toolkit`'s code, you'll find that it is using the offset and length of the WARC record, as returned by the CDX index query, to make a HTTP byte range request to S3 to download the single WARC record we want. It only downloads the response WARC record because our CDX index only has the response records indexed. - -## Task 7: - - - From 3077a7ac406fab62f71a15b091fde349b7af8bb0 Mon Sep 17 00:00:00 2001 From: Laurie Burchell Date: Fri, 6 Jun 2025 10:42:12 +0100 Subject: [PATCH 3/4] docs: reformat WAT so it matches WARC and WET --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8cd3c40..ba01ff3 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,11 @@ Open `whirlwind.warc.wet`: this is the WET derived from our original WARC. We ca WAT (Web ARChive Timestamp) files contain metadata associated with the crawled web pages (e.g. parsed data from the HTTP response headers, links extracted from HTML pages, server response codes etc.). They are useful for analysis that requires understanding the structure of the web. -Open `whirlwind.warc.wat`: this is the WAT derived from our original WARC. Like the WET file, it's also in WARC format. This file contains a metadata record for each response in the WARC. The metadata is stored as json. You might want to feed this json into a pretty-printer to read it more easily. For example, you can save just the json into a file and use `python -m json.tool FILENAME` to pretty-print it. +Open `whirlwind.warc.wat`: this is the WAT derived from our original WARC. Like the WET file, it's also in WARC format. It contains two records: +1) a `warcinfo` record. +2) a `metadata` record: there should be one for each response in the WARC. The metadata is stored as JSON. + +You might want to feed the JSON into a pretty-printer to read it more easily. For example, you can save just the json into a file and use `python -m json.tool FILENAME` to pretty-print it. Now that we've looked at the uncompressed versions of these files to understand their structure, we'll be interacting with compressed WARC, WET, and WAT files for the rest of this tour. This is the usual way we manipulate this data with software tools due to the size of the files. From b7fb6520248a544dd9cee01b460bd94d70f44df2 Mon Sep 17 00:00:00 2001 From: Laurie Burchell Date: Mon, 9 Jun 2025 17:33:09 +0100 Subject: [PATCH 4/4] docs: address Greg's comments, add extra sections for TBD material --- README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ba01ff3..d930eb4 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Let's get started! ## Task 0: Set-up -This tutorial was written on Linux and MacOS. We think it should also work on Windows WSL, but raise an issue if you encounter problems. +This tutorial was written on Linux and MacOS and it should also work on Windows. If you encounter any problems, please raise an issue. ### Clone the repository and create a local Python environment @@ -168,7 +168,7 @@ We have two versions of the index: the CDX index and the columnar index. The CDX ### CDX(J) index -The CDX index files are sorted plain-text files, with each line containing information about a single capture in the WARC. Technically, Common Crawl uses CDXJ index files since the information about each capture is formatted as JSON. We'll use CDX and CDXJ interchangeably in this tour for legacy reasons :) +The CDX index files are sorted plain-text files, with each line containing information about a single capture in the WARC. Technically, Common Crawl uses CDXJ index files since the information about each capture is formatted as JSON. We'll use CDX and CDXJ interchangeably in this tour for legacy reasons 💅 We can create our own CDXJ index from the local WARCs by running: @@ -512,3 +512,19 @@ All of these scripts run the same SQL query and should return the same record (w ## Congratulations! You have completed the Whirlwind Tour of Common Crawl's Datasets using Python! You should now understand different filetypes we have in our corpus and how to interact with Common Crawl's datasets using Python. To see what other people have done with our data, see the [Examples page](https://commoncrawl.org/examples) on our website. Why not join our Discord through the Community tab? + +## Other datasets + +We make more datasets available than just the ones discussed in this Whirlwind Tour. Below is a short introduction to some of these other datasets, along with links to where you can find out more. + +### Web graph + +Common Crawl regularly releases host- and domain-level graphs for visualising the crawl data. The web graphs are available to download [here](https://commoncrawl.org/web-graphs). We provide a [repository](https://github.com/commoncrawl/cc-webgraph) with tools to construct, process, and explore the web graphs. + +### Host index + +The host index is a database which has one row for every web host we know about in each individual crawl. It contains summary information from the crawl, indices, the web graph, and our raw crawler logs. More information is available [here](https://commoncrawl.org/blog/introducing-the-host-index). We also provide a [repository](https://github.com/commoncrawl/cc-host-index) containing examples on how to use the host index. + +### Index annotations + +Index annotations allow users to create a database table that can be joined to Common Crawl's columnar url index or host index. This is useful because we can enrich our datasets with extra information and then use it for analysis. We have a [repository](https://github.com/commoncrawl/cc-index-annotations) with example code for joining annotations to the columnar url index or host index.