|
| 1 | +# Examples |
| 2 | + |
| 3 | +## Simple enrichments |
| 4 | + |
| 5 | +IPTools' Rust implementation gives you speedy answers to basic IP questions like "is this a private IP?" |
| 6 | + |
| 7 | +```python |
| 8 | +>>> import polars as pl |
| 9 | +>>> import polars_iptools as ip |
| 10 | +>>> df = pl.DataFrame({'ip': ['8.8.8.8', '2606:4700::1111', '192.168.100.100', '172.21.1.1', '172.34.5.5', 'a.b.c.d']}) |
| 11 | +>>> df.with_columns(ip.is_private(pl.col('ip')).alias('is_private')) |
| 12 | +shape: (6, 2) |
| 13 | +┌─────────────────┬────────────┐ |
| 14 | +│ ip ┆ is_private │ |
| 15 | +│ --- ┆ --- │ |
| 16 | +│ str ┆ bool │ |
| 17 | +╞═════════════════╪════════════╡ |
| 18 | +│ 8.8.8.8 ┆ false │ |
| 19 | +│ 2606:4700::1111 ┆ false │ |
| 20 | +│ 192.168.100.100 ┆ true │ |
| 21 | +│ 172.21.1.1 ┆ true │ |
| 22 | +│ 172.34.5.5 ┆ false │ |
| 23 | +│ a.b.c.d ┆ false │ |
| 24 | +└─────────────────┴────────────┘ |
| 25 | +``` |
| 26 | + |
| 27 | +## `is_in` but for network ranges |
| 28 | + |
| 29 | +Pandas and Polars have `is_in` functions to perform membership lookups. IPTools extends this to enable IP address membership in IP _networks_. This function works seamlessly with both IPv4 and IPv6 addresses and converts the specified networks into a [Level-Compressed trie (LC-Trie)](https://github.com/Orange-OpenSource/iptrie) for fast, efficient lookups. |
| 30 | + |
| 31 | +```python |
| 32 | +>>> import polars as pl |
| 33 | +>>> import polars_iptools as ip |
| 34 | +>>> df = pl.DataFrame({'ip': ['8.8.8.8', '1.1.1.1', '2606:4700::1111']}) |
| 35 | +>>> networks = ['8.8.8.0/24', '2606:4700::/32'] |
| 36 | +>>> df.with_columns(ip.is_in(pl.col('ip'), networks).alias('is_in')) |
| 37 | +shape: (3, 2) |
| 38 | +┌─────────────────┬───────┐ |
| 39 | +│ ip ┆ is_in │ |
| 40 | +│ --- ┆ --- │ |
| 41 | +│ str ┆ bool │ |
| 42 | +╞═════════════════╪═══════╡ |
| 43 | +│ 8.8.8.8 ┆ true │ |
| 44 | +│ 1.1.1.1 ┆ false │ |
| 45 | +│ 2606:4700::1111 ┆ true │ |
| 46 | +└─────────────────┴───────┘ |
| 47 | +``` |
| 48 | + |
| 49 | +## GeoIP enrichment |
| 50 | + |
| 51 | +Using [MaxMind's](https://www.maxmind.com/en/geoip-databases) _GeoLite2-ASN.mmdb_ and _GeoLite2-City.mmdb_ databases, IPTools provides offline enrichment of network ownership and geolocation. |
| 52 | + |
| 53 | +`ip.geoip.full` returns a Polars struct containing all available metadata parameters. If you just want the ASN and AS organization, you can use `ip.geoip.asn`. |
| 54 | + |
| 55 | +```python |
| 56 | +>>> import polars as pl |
| 57 | +>>> import polars_iptools as ip |
| 58 | + |
| 59 | +>>> df = pl.DataFrame({"ip":["8.8.8.8", "192.168.1.1", "2606:4700::1111", "999.abc.def.123"]}) |
| 60 | +>>> df.with_columns([ip.geoip.full(pl.col("ip")).alias("geoip")]) |
| 61 | + |
| 62 | +shape: (4, 2) |
| 63 | +┌─────────────────┬─────────────────────────────────┐ |
| 64 | +│ ip ┆ geoip │ |
| 65 | +│ --- ┆ --- │ |
| 66 | +│ str ┆ struct[11] │ |
| 67 | +╞═════════════════╪═════════════════════════════════╡ |
| 68 | +│ 8.8.8.8 ┆ {15169,"GOOGLE","","NA","","",… │ |
| 69 | +│ 192.168.1.1 ┆ {0,"","","","","","","",0.0,0.… │ |
| 70 | +│ 2606:4700::1111 ┆ {13335,"CLOUDFLARENET","","","… │ |
| 71 | +│ 999.abc.def.123 ┆ {null,null,null,null,null,null… │ |
| 72 | +└─────────────────┴─────────────────────────────────┘ |
| 73 | + |
| 74 | +>>> df.with_columns([ip.geoip.asn(pl.col("ip")).alias("asn")]) |
| 75 | +shape: (4, 2) |
| 76 | +┌─────────────────┬───────────────────────┐ |
| 77 | +│ ip ┆ asn │ |
| 78 | +│ --- ┆ --- │ |
| 79 | +│ str ┆ str │ |
| 80 | +╞═════════════════╪═══════════════════════╡ |
| 81 | +│ 8.8.8.8 ┆ AS15169 GOOGLE │ |
| 82 | +│ 192.168.1.1 ┆ │ |
| 83 | +│ 2606:4700::1111 ┆ AS13335 CLOUDFLARENET │ |
| 84 | +│ 999.abc.def.123 ┆ │ |
| 85 | +└─────────────────┴───────────────────────┘ |
| 86 | +``` |
| 87 | + |
| 88 | +## Spur enrichment |
| 89 | + |
| 90 | +[Spur](https://spur.us/) is a commercial service that provides "data to detect VPNs, residential proxies, and bots". One of its offerings is a [Maxmind mmdb format](https://docs.spur.us/feeds?id=feed-export-utility) of at most 2,000,000 "busiest" Anonymous or Anonymous+Residential ips. |
| 91 | + |
| 92 | +`ip.spur.full` returns a Polars struct containing all available metadata parameters. |
| 93 | + |
| 94 | +```python |
| 95 | +>>> import polars as pl |
| 96 | +>>> import polars_iptools as ip |
| 97 | + |
| 98 | +>>> df = pl.DataFrame({"ip":["8.8.8.8", "192.168.1.1", "999.abc.def.123"]}) |
| 99 | +>>> df.with_columns([ip.spur.full(pl.col("ip")).alias("spur")]) |
| 100 | + |
| 101 | +shape: (3, 2) |
| 102 | +┌─────────────────┬─────────────────────────────────┐ |
| 103 | +│ ip ┆ geoip │ |
| 104 | +│ --- ┆ --- │ |
| 105 | +│ str ┆ struct[7] │ |
| 106 | +╞═════════════════╪═════════════════════════════════╡ |
| 107 | +│ 8.8.8.8 ┆ {0.0,"","","","","",null} │ |
| 108 | +│ 192.168.1.1 ┆ {0.0,"","","","","",null} │ |
| 109 | +│ 999.abc.def.123 ┆ {null,null,null,null,null,null… │ |
| 110 | +└─────────────────┴─────────────────────────────────┘ |
| 111 | +``` |
0 commit comments