简体   繁体   中英

How to parse movie script in a dictionary

I have data which looks like this:

script = """
JOSH:
How do I know if this works?

MICHAEL:
You would know

JOSH:
But how? 

DAN:
How indeed? I don't really know. 


UNKNOWN: 
I am unknown
"""

I want to find the text spoken by each character in [Josh, Michael. Dan] [Josh, Michael. Dan] and ignore UNKNOWN . Note that in this toy example, each character has exactly one line per turn but it is more in the real thing.

I'd like to ultimately return a dictionary of the form

lines = {}

lines[Josh] = ["How do I know if this works?", "But how?"]

lines[Michael] = "You would know"

lines[Dan] = ["How indeed?", "I don't really know."]

Or perhaps another data structure would be better.

I added a few more lines for each name to get close to the real task, and used regular expressions to do it safely:

import re
import pprint

script = """
JOSH:
How do I know if this works?
And here is another line for JOSH

MICHAEL:
You would know
And another line for MICHAEL

JOSH:
But how? 
One more for JOSH

DAN:
How indeed? I don't really know. 
One more for DAN


UNKNOWN: 
I am unknown
"""

# split by paragraph, by at least 2 consecutive newlines
pars = re.split(r'\n\n+', script, re.S + re.M)
d = {}

for p in pars:  # for each paragraph
    # capture the name (anchored to beginning of line and all capitals)
    # and the rest of the paragraph - (.*)
    name, txt = re.search(r'^([A-Z]+):(.*)', p, re.S + re.M).group(1, 2)

    # Each sentence as a list item
    if name in d:
        d[name] += txt.strip().split('\n')
    else:
        d[name] = txt.strip().split('\n')



pprint.pprint(d)    

Output

{'DAN': ["How indeed? I don't really know. ", 'One more for DAN'],
 'JOSH': ['How do I know if this works?',
      'And here is another line for JOSH',
      'But how? ',
      'One more for JOSH'],
 'MICHAEL': ['You would know', 'And another line for MICHAEL'],
 'UNKNOWN': ['I am unknown']}

you can split the script into "blocks" on a double newline.

each block starts with a line containing the speaker, the rest is the text

try this:

from collections import defaultdict

script = """\
JOSH:
How do I know if this works?

MICHAEL:
You would know

JOSH:
But how? 

DAN:
How indeed? I don't really know. 


UNKNOWN: 
I am unknown
"""

line_blocks = script.split("\n\n")

wanted_names = {name.upper() + ":": name for name in ["Josh", "Michael", "Dan"]}

result = defaultdict(list)

for block in line_blocks:
    name, text = block.split("\n", 1)
    if name in wanted_names:
        result[wanted_names[name]].append(text)

print(result["Josh"])
print(result["Michael"])
print(result["Dan"])

Output:

['How do I know if this works?', 'But how? ']
['You would know']
["How indeed? I don't really know. "]

I am not really sure about your final structure but, if it is very consistent, you can use regex.

Here's my code:

import re

script = """
JOSH:
How do I know if this works?

MICHAEL:
You would know

JOSH:
But how? 

DAN:
How indeed? I don't really know. 

UNKNOWN:
I am unknown

"""
# This regex is extracting two groups.
# The first one is one or more words before the ":" (the character's name)
# The second one will be everything between newlines (the line)
matcher = re.compile("(\w+):\n(.*)\n")
groups_extracted = matcher.findall(script)

result = {}

for element in groups_extracted:
    # A little verbosity to make understanding easier
    author = element[0]
    line = element[1]
    if author in result:
        # In case the author name is already in the result dict
        # we just append a new line on his / her name
        result[author].append(line)
    else:
        # Otherwise the author name needs to be added to the dict
        # from scratch with his / her 1st line
        result[author] = [line]

print(result)

print(result['JOSH'])

{'JOSH': ['How do I know if this works?', 'But how? '], 'MICHAEL': ['You would know'], 'DAN': ["How indeed? I don't really know. "], 'UNKNOWN': ['I am unknown']}

['How do I know if this works?', 'But how? ']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM