[Python] Spacy rules matching entities before text

Discussão em 'Python' iniciado por Stack, Junho 27, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to write a spacy parser to extract the names and terms of a contract. To do that, I've written a rule to extract the sellers and buyers, except it's extracting multiple times over a simple sentence.

    Here's my rule

    [{"label": "seller", "pattern": [{"ENT_TYPE": "PERSON", "OP": "{1,2}"}, { "OP": "*"}, {"TEXT": "seller"}]},
    {"label": "buyer", "pattern": [{"ENT_TYPE": "PERSON", "OP": "{1,2}"}, { "OP": "*"}, {"TEXT": "buyer"}]},]


    Which results in spans like this:

    span seller Text: john e. smith and wife judy c. smith, seller
    span seller Text: e. smith and wife judy c. smith, seller
    span seller Text: smith and wife judy c. smith, seller
    span seller Text: judy c. smith, seller
    span seller Text: c. smith, seller
    span seller Text: smith, seller


    It seems that spacy is chunking the person entities. How can I produce a rule that matches multiple sellers (or buyers), but doesn't cut them up like this example?

    My code is below.

    #!/usr/bin/env python3

    import spacy
    from spacy.tokens import SpanGroup, DocBin, Span
    from spacy import displacy
    import bodytext
    import sys
    rules = [{"label": "seller", "pattern": [{"ENT_TYPE": "PERSON", "OP": "{1,2}"}, { "OP": "*"}, {"TEXT": "seller"}]},
    {"label": "buyer", "pattern": [{"ENT_TYPE": "PERSON", "OP": "{1,2}"}, { "OP": "*"}, {"TEXT": "buyer"}]},]
    nlp = spacy.load("en_core_web_lg")
    ruler = nlp.add_pipe("span_ruler")
    ruler.add_patterns(rules)

    text = "THIS AGREEMENT made on this 12 day of December, 2008, between John E. Smith and wife Judy C. Smith, Seller (whether one or more), whose address is: 1234 CRD 5000, midland, Texas, 79221-2016, and real estate investors, LLC, Buyer, whose address is: 4321 Harvard Ave, Midland, Texas 79701. "
    doc = nlp(text.lower())

    doc.spans["test"] = SpanGroup(doc)
    db = DocBin()

    for sentence in doc.sents:
    for span in doc.spans["ruler"]:
    print("span "+ span.label_+" Text: "+span.text)
    if span.start >= sentence.start and span.end <= sentence.end:
    doc.spans["test"] += [
    Span(doc, start=sentence.start, end=sentence.end, label=span.label_)
    ]
    doc.set_ents(entities=[span], default="unmodified")

    Continue reading...

Compartilhe esta Página