最近映画視聴記録がどうのという記事を書いていたのですが、映画関連で昔パルプフィクション絡みのやつを書いたことを思い出しました。
内容はタイトルの通りなのですが、以前の記事ではやり残しがありました。
プログラム歴も増えてきたので今なら出来るっしょということでリメイク版です。
前回のおさらい
paloma69.hatenablog.com
- 台本上のfワードは169個
- やり残し
- セリフの成形
- 件数の表示
- 誰が何回言ったかのサマリ
コード
今回は全処理関数化してライブラリ的に呼び出せる様にしました。
(わざわざ呼び出して使う機会は無いと思うが)
引数の値もう少し統一感出せばよかったな。
今回も一応全編通して伏字にします。
from bs4 import BeautifulSoup
import re
import collections
def create_quote_list():
with open('Pulp-fiction.html', 'r', encoding='utf-8') as f:
soup = BeautifulSoup(f.read(), 'html.parser')
lines = []
for x in soup.findAll('b'):
lines.append((x.text, x.next_sibling))
return lines
def into_list(l, chara, quote):
shaping_charactor = chara.replace("\n", "").replace(" ", "").replace("(O.S.)", "")
if shaping_charactor == 'CLOSEUP・MIA':
shaping_charactor = 'MIA'
l.append([shaping_charactor, quote])
def scraping_words(script_list):
s_reg = re.compile('.+[fF]xxk.+')
flist = []
for l in script_list:
split_sentense = re.split('[,.!?]|and', str(l[1]))
for x in split_sentense:
w = re.search(s_reg, x)
if bool(w) is True:
s = w.group().replace("\n", " ").replace(" ", "")
if 'AND' in l[0]:
for y in l[0].split('AND'):
into_list(flist, y, s)
else:
into_list(flist, l[0], s)
return flist
def fcounter(l):
max_c, max_w = shapes(l)
clist = []
for x in l:
clist.append(x[0])
c = collections.Counter(clist).most_common()
for x in c:
c, w = x
print(c.ljust(max_c), w)
def shapes(l):
max_c, max_w = 0,0
for f in l:
if len(f[0]) > max_c:
max_c = len(f[0])
if len(f[1]) > max_w:
max_w = len(f[1])
return max_c, max_w
def fquote(l):
max_c, max_w = shapes(l)
n = 1
for x in l:
print(n, x[0].ljust(max_c), x[1].ljust(max_w))
n +=1
def main():
lines = create_quote_list()
flist = scraping_words(lines)
print('*' * 10, 'print f word list', '*' * 10)
fquote(flist)
print('*' * 10, 'print f word count', '*' * 10)
fcounter(flist)
if __name__ == '__main__':
main()
スクリプト叩いて終了では味気無いのでインタラクティブシェルでインポートして少し見ましょう。
本当はこの呼び出し方は非推奨です。
>>> from pulp import *
前回と同じくimdbのサイトにscriptがあるので、これをダウンロードしてつかいます。
https://imsdb.com/scripts/Pulp-Fiction.html
スクレイピングのライブラリはBeautifulSoupです。
スクレイピング処理も呼び出して格納。
>>> lines = create_quote_list()
HTML構成
上記サイトのscriptファイルはしっかりと階層化はされてなくて、
bタグでシチュエーションや登場人物、次の階層(タグなし)に状況やセリフが書かれています。
タグが無くてもnext_siblingというmethodで取得できます。
create_quote_list()内でbタグとその次のセリフを取得してます。
for x in soup.findAll('b'):
lines.append((x.text, x.next_sibling))
取得した値はこう。
>>> lines[0]
(' "PULP FICTION"\n', '\n By\n\n
Quentin Tarantino & Roger Avary\n\n')
>>> lines[10]
(' YOUNG WOMAN\n', '
You sound like a duck.\n (imitates a duck)\n Quack, quack, quack, quack, quack, \n quack, quack...\n\n')
>>> lines[20]
(' YOUNG WOMAN\n', '
Did they hurt the little girl?\n\n')
スペース、改行記号の処理は別関数のshapingで行います。
ワードの取得
正規表現でワードと前後の文を抽出します。
4文字だけだと同じ文字が続くだけなので、結構バリエーションが出てくるのでせっかくだし前後も取ることにしました。
/w+等使って文章ごとに取りたかったのですが特殊文字や余剰スペースの処理で上手く全件ヒットとはならなかったのでフレーズごとに取得してます。
>>> f = scraping_words(lines)
>>> f[0]
['YOUNGMAN', ' I sound like a sensible fxxking man']
>>> f[10]
['YOUNGMAN', ' fxxk it']
>>> f[100]
['JULES', " Don't you fxxkin' do "]
>>> f[20]
['VINCENT', " but you're in the same fxxkin' "]
少し短いですが誰がどんな感じのこと言ってるかの雰囲気はわかります。
カウントのためリストに格納
上記と同じくscraping_words()の処理の話ですがカウントできるよう取得項目を人物、セリフに分割してリストにいれていきます。
文章を正規表現で抜き出すというのはやはりブレが出るため難しく、フレーズごとに分割してから対象のワードをひっかける方法にしました。
(件数が合わなくてあれ?となり何回か方法を施行しました)
一件だけ2人が同時に叫ぶ所がありますが、人物をカウントしたいのでここもさらに分割してます。
def scraping_words(script_list):
s_reg = re.compile('.+[fF]xxk.+')
flist = []
for l in script_list:
split_sentense = re.split('[,.!?]|and', str(l[1]))
for x in split_sentense:
w = re.search(s_reg, x)
if bool(w) is True:
s = w.group().replace("\n", " ").replace(" ", "")
if 'AND' in l[0]:
for y in l[0].split('AND'):
into_list(flist, y, s)
else:
into_list(flist, l[0], s)
また、スクリプト上で登場人物の表記が少しブレるので修正します。
セリフだけで画角にいないと台本に(S.O.)と言う表記が付くらしいです。
あとミアがCLOSEUPと付くシーンが一件だけあるのでこれも修正。
これらを取り除いてリストに入れるのがinto_listです。
後でアウトプットは出てくるのでコードだけおさらい。
def into_list(l, chara, quote):
shaping_charactor = chara.replace("\n", "").replace(" ", "").replace("(O.S.)", "")
if shaping_charactor == 'CLOSEUP・MIA':
shaping_charactor = 'MIA'
l.append([shaping_charactor, quote])
何回言ったかのカウンタは別関数でまとめます。
def fcounter(l):
max_c, max_w = shapes(l)
clist = []
for x in l:
clist.append(x[0])
c = collections.Counter(clist).most_common()
for x in c:
c, w = x
print(c.ljust(max_c), w)
出力
最後にアウトプット。
まずはfワードを全件出します。
罵詈雑言の嵐です(笑)
>>> fquote(f)
1 YOUNGMAN I sound like a sensible fxxking man
2 YOUNGMAN takin' the same fxxkin' risk as when
3 YOUNGMAN fxxkin' A it worked
4 YOUNGMAN but a fxxkin' phone
5 YOUNGMAN lift a fxxkin' finger
6 YOUNGMAN fxxkin' speak English
7 YOUNGMAN don't know what it fxxkin' means
8 YOUNGMAN one of those gook motherfxxkers'
9 YOUNGMAN fifteen fxxkin' generations
10 YOUNGMAN counter with a fxxkin' Magnum
11 YOUNGMAN fxxk it
12 YOUNGMAN gonna really give a fxxk you're
13 HONEYBUNNY Any of you fxxkin' pricks move
14 HONEYBUNNY motherfxxkers
15 JULES man ・I'm fxxkin' goin'
16 VINCENT they wouldn't know what the fxxk a
17 VINCENT they fxxkin' drown 'em in it
18 VINCENT We should have fxxkin' shotguns
19 JULES Marsellus fxxked his ass up
20 VINCENT fxxk her
21 VINCENT but you're in the same fxxkin'
22 JULES the same fxxkin' thing
23 JULES ain't even the same fxxkin' sport
24 JULES massages ・I'm the foot fxxkin'
25 JULES fxxk you
26 JULES fxxk you
27 JULES motherfxxkin-house
28 JULES fxxkin' up the
29 JULES Motherfxxker do that to
30 JULES I'd kill'a motherfxxker
31 VINCENT That's what's so fxxkin'
32 VINCENT fxxkin' Marsellus knew it
33 VINCENT shoulda known fxxkin' better
34 VINCENT his fxxkin' wife
35 JULES You'a smart motherfxxker
36 BRETT are about how fxxked up things got
37 JULES English-motherfxxker-can-you-speak-
38 JULES motherfxxker
39 JULES Then why did you try to fxxk 'im
40 JULES Ya tried ta fxxk
41 MARSELLUS motherfxxker
42 MARSELLUS that's a hard motherfxxkin' fact of
43 MARSELLUS motherfxxkers who thought their ass
44 MARSELLUS fxxkin' wit ya
45 MARSELLUS fxxk pride
46 VINCENT man's fxxkin' wife
47 LANCE But this one's a fxxkin'
48 LANCE any ol' day of the fxxkin' week
49 LANCE Coke is fxxkin'
50 LANCE in a big fxxkin' way
51 VINCENT You know what some fxxker did to it
52 VINCENT fxxkin' keyed it
53 LANCE that's fxxked up
54 VINCENT out five fxxkin' days ・five days
55 VINCENT some dickless piece of shit fxxks
56 LANCE They should be fxxkin' killed
57 LANCE You don't fxxk
58 VINCENT What the fxxk is this place
59 VINCENT That's a pretty fxxkin'
60 VINCENT but it's pretty fxxkin'
61 MIA shit the fxxk up for a minute
62 MIA like it's on fxxking fire)
63 JODY I thought you told those fxxkin'
64 LANCE tell this fxxkin' asshole right now
65 LANCE this fxxkin' late
66 VINCENT fxxkin' trouble man
67 VINCENT fxxkin'Doing on me
68 LANCE fxxkin' joking with you
69 LANCE be bringing some fxxked up pooh-butt
70 LANCE Then bite the fxxkin' bullet
71 LANCE She ain't my fxxkin' problem
72 LANCE fxxked her up
73 LANCE your car in my fxxkin' house
74 LANCE fxxkin' phone ・
75 LANCE that fxxked up bitch in my house
76 VINCENT This fxxked up bitch is Marsellus
77 VINCENT Now if she fxxkin'
78 JODY What the fxxk's goin' on
79 JODY here being nobody knows what the fxxk they're doing
80 LANCE Get the fxxkin' shot
81 VINCENT Get the fxxkin' shot
82 VINCENT I'm not fxxkin' stoppin' you
83 LANCE My black fxxkin' medical book
84 VINCENT fxxk the
85 VINCENT Quit fxxkin' around man
86 VINCENT This ain't a fxxkin' joke man
87 MARSELLUS this motherfxxker
88 FABIENNE Shut up fxxk head
89 BUTCH Yes I've fxxkin' looked
90 BUTCH What the fxxk do you think I'm doing
91 BUTCH that was my father's fxxkin'
92 BUTCH all I gave a fxxk about was my watch
93 BUTCH Of all the fxxkin' things she coulda
94 MARSELLUS I'm pretty fxxkin' far from
95 BUTCH fxxk the bags
96 BUTCH we gotta hit the fxxkin' road
97 JULES blowing them all away while they're fxxkin' around
98 VINCENT Why the fxxk didn't you tell us about
99 JULES We should be fxxkin' dead right now
100 JULES We should be fxxkin' dead
101 JULES Don't you fxxkin' do
102 JULES What just happened was a fxxkin'
103 VINCENT Chill the fxxk out
104 JULES We should be fxxkin' dead now
105 JULES I want you to fxxkin' acknowledge
106 JULES eyes are wide fxxkin' open
107 VINCENT What the fxxk does that mean
108 VINCENT ・you're fxxkin' freakin' out
109 JULES What the fxxk's happening
110 JULES Why the fxxk did you do that
111 JULES The car didn't hit no motherfxxkin'
112 JULES motherfxxker
113 JULES drenched in fxxkin' blood
114 JULES fxxk we're gonna go
115 JULES We gotta be real fxxkin' delicate
116 JULES What the fxxk did you just do to his
117 JULES didn't look like a fxxkin' Maxie
118 JULES fxxk it
119 JULES gourmet fxxkin' shit on us
120 JIMMIE how fxxkin' good it is
121 JIMMIE fxxkin' business
122 JIMMIE fxxkin' divorced
123 JIMMIE get fxxkin' divorced
124 JIMMIE ・don't fxxkin' Jimmie me
125 JIMMIE than get the fxxk out of my house
126 JULES fxxk up your shit
127 MARSELLUS No fxxkin' shit she'll freak
128 JULES motherfxxkin' "ifs
129 JULES motherfxxker
130 MARSELLUS I'm on the motherfxxker
131 THEWOLF the fxxk outta Dodge
132 JULES motherfxxker's tip-top
133 THEWOLF you better fxxkin' do it
134 THEWOLF clean the fxxkin' car
135 JULES This is some fxxked-up
136 JULES The motherfxxker who said that
137 VINCENT it's fxxkin' dangerous to be
138 JULES mushroom-cloud-layin' motherfxxker
139 JULES fxxk am I doin' in the back
140 JULES the motherfxxker should be on brain
141 JULES that water's fxxkin' cold
142 JULES motherfxxker
143 THEWOLF does a fxxkin' thing 'til I do
144 THEWOLF I drive real fxxkin' fast
145 JULES motherfxxker
146 JULES motherfxxkin' charmin' pig
147 JULES my fxxkin' car keys
148 JULES That's what's fxxkin' wit' me
149 VINCENT of fxxkin' zombies
150 VINCENT gonna be ・a fxxkin' bum
151 VINCENT Stop fxxkin' talkin' like that
152 HONEYBUNNY Any of you fxxkin' pricks move
153 HONEYBUNNY motherfxxkers
154 HONEYBUNNY Now mean fxxkin' now
155 HONEYBUNNY do it or fxxking die
156 PUMPKIN now git your fxxkin' ass
157 JULES Keep your fxxkin' mouth closed
158 PUMPKIN unload right in your fxxkin' face
159 HONEYBUNNY your fxxkin' head off
160 HONEYBUNNY gonna fxxkin' die bad
161 JULES And when motherfxxkers
162 JULES that's when motherfxxkers
163 JULES fxxkin' fried chicken
164 VINCENT What the fxxk's goin' on here
165 JULES Motherfxxker on it
166 JULES with "Bad Motherfxxker" embroidered on it
167 JULES That's my bad motherfxxker
168 JULES shut the fxxk up
169 JULES say to a motherfxxker 'fore you popped
169件で前回と同じ件数です。OK。
続いて何回言ったかカウンタ。
やはり出演シーンの多い主人公達が多いですね。
本当は同一人物がいるのですが一応ネタバレになるのでここは手つけずです。
>>> fcounter(f)
JULES 59
VINCENT 35
LANCE 19
YOUNGMAN 12
MARSELLUS 9
HONEYBUNNY 8
BUTCH 7
JIMMIE 6
THEWOLF 5
JODY 3
MIA 2
PUMPKIN 2
BRETT 1
FABIENNE 1
OK。
成形もうまいこと効いていていい感じに出力できました!
まとめ
フタを開けてみると成形のコードがほとんどでスクレイピングや正規表現は全然やってませんでしたw
やはりセリフを正規表現で抜き出すというのは文章やワードなどかなりのバリエーションがあり難しいです。
前述しましたが結局フレーズ毎に区切ってからワードを抜き出すという方法に落ち着きました。
とりあえず望む結果になったのでよしとします。
さすがに前回より日が経っているだけあって積み残しの解決も出来たしコードの書き方も少しは綺麗に出来たかなと思います。
最近パルプフィクション見てないのですがこの記事書いてたらまた見たくなってしまいました。