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.
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.
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.
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
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.
- Run
extract_us_phone_numberon the FAQ line that ends with the number and compare. - Use
extract_text_beforeto get the order number out of Order A17 has not arrived. - Print
US_PHONE_NUMBERS_PATTERNand find the part that makes the area code optional.
Little by little, you're building something great.