Unstructuredunstructured 0.27.6 · Python 3.11+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
21 small wins to finish your pathNext lesson

Pulling values out of text

A cleaner rewrites the text. An extractor leaves it alone and returns something found inside it. The difference matters because one of these functions is stricter than it looks.

Addresses come out of any element easily enough.

Example
from unstructured.partition.auto import partition
from unstructured.cleaners.extract import extract_email_address

for element in partition("faq.txt"):
    found = extract_email_address(element.text)
    if found:
        print(found)

Two addresses out of the one line that had them, returned as a list. Elements with no address return an empty list, which is why the if is there.

The one that looks broken

Phone numbers have a function too. Try it on the customer's email from lesson 13.

Example
from unstructured.partition.auto import partition
from unstructured.cleaners.extract import extract_us_phone_number

line = partition("ravi.eml")[1].text
print(repr(line))
print(repr(extract_us_phone_number(line)))

An empty string, from a line with a phone number plainly in the middle of it. Nothing raised and nothing warned.

The reason is in the pattern. US_PHONE_NUMBERS_PATTERN ends with \s*$, which means the number has to be the last thing in the string. It works on Call the desk on 215-867-5309 and not on a sentence that continues afterwards. The documentation only shows the first shape.

Fixing it

The pattern is exported, so the anchor can be taken off and the search run anywhere in the line.

Example
import re
from unstructured.nlp.patterns import US_PHONE_NUMBERS_PATTERN
from unstructured.partition.auto import partition

anywhere = US_PHONE_NUMBERS_PATTERN.replace(r"\s*$", "")
line = partition("ravi.eml")[1].text
print(re.search(anywhere, line).group().strip())

The number, from the middle of the sentence. This is worth knowing beyond phone numbers: every pattern the library matches on lives in unstructured.nlp.patterns, and reading the one that is failing you takes a minute.

Two more worth knowing

Example
from unstructured.cleaners.extract import extract_datetimetz, extract_text_after

print(extract_datetimetz("Mon, 3 Mar 2025 09:12:00 +0530"))
print(extract_text_after("Subject: Order A17 has not arrived", r"Subject:"))

extract_datetimetz returns a real datetime with the timezone kept, which is what you want for sorting a mailbox. extract_text_after takes a regular expression and returns everything past the first match, which is how you pull a value out from behind a label.

There is no extractor that finds a date anywhere inside a sentence, and no extractor for an order number or a postcode. The list is short and specific: addresses, IP addresses, phone numbers, dates, bullets, and text before or after a pattern. For anything else you write the regular expression yourself, and the ones above are worth reading first as examples.
Try it yourself
  • Run extract_us_phone_number on the FAQ line that ends with the number and compare.
  • Use extract_text_before to get the order number out of Order A17 has not arrived.
  • Print US_PHONE_NUMBERS_PATTERN and find the part that makes the area code optional.

Little by little, you're building something great.