parent
3356a40e22
commit
e6523d6902
After Width: | Height: | Size: 8.9 KiB |
@ -0,0 +1,394 @@
|
|||||||
|
# BoxOfficeMojo Builders
|
||||||
|
|
||||||
|
You can find items using the lists on [boxofficemojo.com](https://www.boxofficemojo.com/) (BoxOfficeMojo).
|
||||||
|
|
||||||
|
No configuration is required for these builders.
|
||||||
|
|
||||||
|
??? blank "`mojo_domestic` - Uses the Domestic Box Office.<a class="headerlink" href="#mojo-domestic" title="Permanent link">¶</a>"
|
||||||
|
|
||||||
|
<div id="mojo-domestic" />Uses the Domestic Box Office to collection items.
|
||||||
|
|
||||||
|
<hr style="margin: 0px;">
|
||||||
|
|
||||||
|
**Works With:** Movies, Playlists, and Custom Sort
|
||||||
|
|
||||||
|
**Builder Attribute:** `mojo_domestic`
|
||||||
|
|
||||||
|
**Builder Value:** [Dictionary](../../pmm/yaml.md#dictionaries) of Attributes
|
||||||
|
|
||||||
|
??? blank "`range` - Determines the type of time range of the Box Office"
|
||||||
|
|
||||||
|
Determines the type of the time range of the Box Office.
|
||||||
|
|
||||||
|
**Allowed Values:** `daily`, `weekend`, `weekly`, `monthly`, `quarterly`, `yearly`, `season`, or `holiday`
|
||||||
|
|
||||||
|
??? blank "`year` - Determines the year of the Box Office"
|
||||||
|
|
||||||
|
Determines the year of the Box Office. This attribute is ignored for the `daily` range.
|
||||||
|
|
||||||
|
**Default Value:** `current`
|
||||||
|
|
||||||
|
**Allowed Values:** Number between 1977 and the current year, `current`, or relative current (`current-#`; where
|
||||||
|
`#` is the number of year before the current)
|
||||||
|
|
||||||
|
??? blank "`range_data` - Determines the actual time range of the Box Office"
|
||||||
|
|
||||||
|
Determines the actual time range of the Box Office. The input for this value changes depending on the value
|
||||||
|
of `range`. This attribute is required for all ranges expect the `yearly` range.
|
||||||
|
|
||||||
|
**Daily Allowed Values:** Date in the format `MM-DD-YYYY`, `current`, or relative current (`current-#`; where
|
||||||
|
`#` is the number of days before the current)
|
||||||
|
|
||||||
|
**Weekend Allowed Values:** Week Number between 1-53, `current`, or relative current (`current-#`; where `#`
|
||||||
|
is the number of days before the current)
|
||||||
|
|
||||||
|
**Weekly Allowed Values:** Week Number between 1-53, `current`, or relative current (`current-#`; where `#`
|
||||||
|
is the number of days before the current)
|
||||||
|
|
||||||
|
**Monthly Allowed Values:** `january`, `february`, `march`, `april`, `may`, `june`, `july`, `august`,
|
||||||
|
`september`, `october`, `november`, `december`, `current`, or relative current (`current-#`; where `#` is the
|
||||||
|
number of days before the current)
|
||||||
|
|
||||||
|
**Quarterly Allowed Values:** `q1`, `q2`, `q3`, `q4`, `current`, or relative current (`current-#`; where `#`
|
||||||
|
is the number of days before the current)
|
||||||
|
|
||||||
|
**Season Allowed Values:** `winter`, `spring`, `summer`, `fall`, `holiday`, or `current`
|
||||||
|
|
||||||
|
**Holiday Allowed Values:** `new_years_day`, `new_year_weekend`, `mlk_day`, `mlk_day_weekend`,
|
||||||
|
`presidents_day`, `presidents_day_weekend`, `easter`, `easter_weekend`, `memorial_day`, `memorial_day_weekend`,
|
||||||
|
`independence_day`, `independence_day_weekend`, `labor_day`, `labor_day_weekend`, `indigenous_day`,
|
||||||
|
`indigenous_day_weekend`, `halloween`, `thanksgiving`, `thanksgiving_3`, `thanksgiving_4`, `thanksgiving_5`,
|
||||||
|
`post_thanksgiving_weekend`, `christmas_day`, `christmas_weekend`, or `new_years_eve`
|
||||||
|
|
||||||
|
??? blank "`limit` - The maximum number of result to return"
|
||||||
|
|
||||||
|
This determines the maximum number of results to return. If there are less results then the limit then all will
|
||||||
|
be returned.
|
||||||
|
|
||||||
|
**Default Value:** Returns all results
|
||||||
|
|
||||||
|
**Allowed Values:** Number greter than 0
|
||||||
|
|
||||||
|
???+ example "Example"
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
collections:
|
||||||
|
|
||||||
|
Current Domestic Box Office:
|
||||||
|
mojo_domestic:
|
||||||
|
range: yearly
|
||||||
|
year: current
|
||||||
|
|
||||||
|
Last Year's Domestic Box Office:
|
||||||
|
mojo_domestic:
|
||||||
|
range: yearly
|
||||||
|
year: current-1
|
||||||
|
|
||||||
|
Last Months Top 10 Domestic Box Office:
|
||||||
|
mojo_domestic:
|
||||||
|
range: monthly
|
||||||
|
year: current-1
|
||||||
|
limit: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
??? blank "`mojo_international` - Uses the International Box Office.<a class="headerlink" href="#mojo-international" title="Permanent link">¶</a>"
|
||||||
|
|
||||||
|
<div id="mojo-international" />Uses the International Box Office to collection items.
|
||||||
|
|
||||||
|
<hr style="margin: 0px;">
|
||||||
|
|
||||||
|
**Works With:** Movies, Playlists, and Custom Sort
|
||||||
|
|
||||||
|
**Builder Attribute:** `mojo_international`
|
||||||
|
|
||||||
|
**Builder Value:** [Dictionary](../../pmm/yaml.md#dictionaries) of Attributes
|
||||||
|
|
||||||
|
??? blank "`range` - Determines the type of time range of the Box Office"
|
||||||
|
|
||||||
|
Determines the type of the time range of the Box Office.
|
||||||
|
|
||||||
|
**Allowed Values:** `weekend`, `monthly`, `quarterly`, or `yearly`
|
||||||
|
|
||||||
|
??? blank "`chart` - Determines the chart you want to use"
|
||||||
|
|
||||||
|
Determines the chart you want to use.
|
||||||
|
|
||||||
|
**Default Value:** `international`
|
||||||
|
|
||||||
|
**Allowed Values:** Item in the drop down found [here](https://www.boxofficemojo.com/intl/)
|
||||||
|
|
||||||
|
??? blank "`year` - Determines the year of the Box Office"
|
||||||
|
|
||||||
|
Determines the year of the Box Office.
|
||||||
|
|
||||||
|
**Default Value:** `current`
|
||||||
|
|
||||||
|
**Allowed Values:** Number between 1977 and the current year, `current`, or relative current (`current-#`; where
|
||||||
|
`#` is the number of year before the current)
|
||||||
|
|
||||||
|
??? blank "`range_data` - Determines the actual time range of the Box Office"
|
||||||
|
|
||||||
|
Determines the actual time range of the Box Office. The input for this value changes depending on the value
|
||||||
|
of `range`. This attribute is required for all ranges expect the `yearly` range.
|
||||||
|
|
||||||
|
**Weekend Allowed Values:** Week Number between 1-53, `current`, or relative current (`current-#`; where `#`
|
||||||
|
is the number of days before the current)
|
||||||
|
|
||||||
|
**Monthly Allowed Values:** `january`, `february`, `march`, `april`, `may`, `june`, `july`, `august`,
|
||||||
|
`september`, `october`, `november`, `december`, `current`, or relative current (`current-#`; where `#` is the
|
||||||
|
number of days before the current)
|
||||||
|
|
||||||
|
**Quarterly Allowed Values:** `q1`, `q2`, `q3`, `q4`, `current`, or relative current (`current-#`; where `#`
|
||||||
|
is the number of days before the current)
|
||||||
|
|
||||||
|
??? blank "`limit` - The maximum number of result to return"
|
||||||
|
|
||||||
|
This determines the maximum number of results to return. If there are less results then the limit then all will
|
||||||
|
be returned.
|
||||||
|
|
||||||
|
**Default Value:** Returns all results
|
||||||
|
|
||||||
|
**Allowed Values:** Number greter than 0
|
||||||
|
|
||||||
|
???+ example "Example"
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
collections:
|
||||||
|
|
||||||
|
Current International Box Office:
|
||||||
|
mojo_international:
|
||||||
|
range: yearly
|
||||||
|
year: current
|
||||||
|
|
||||||
|
Last Year's International Box Office:
|
||||||
|
mojo_international:
|
||||||
|
range: yearly
|
||||||
|
year: current-1
|
||||||
|
|
||||||
|
Last Months Top 10 German Box Office:
|
||||||
|
mojo_international:
|
||||||
|
range: monthly
|
||||||
|
chart: germany
|
||||||
|
year: current-1
|
||||||
|
limit: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
??? blank "`mojo_world` - Uses the Worldwide Box Office.<a class="headerlink" href="#mojo-world" title="Permanent link">¶</a>"
|
||||||
|
|
||||||
|
<div id="mojo-world" />Uses the [Worldwide Box Office](https://www.boxofficemojo.com/year/world/) to collection items.
|
||||||
|
|
||||||
|
<hr style="margin: 0px;">
|
||||||
|
|
||||||
|
**Works With:** Movies, Playlists, and Custom Sort
|
||||||
|
|
||||||
|
**Builder Attribute:** `mojo_world`
|
||||||
|
|
||||||
|
**Builder Value:** [Dictionary](../../pmm/yaml.md#dictionaries) of Attributes
|
||||||
|
|
||||||
|
??? blank "`year` - The year of the Worldwide Box Office"
|
||||||
|
|
||||||
|
This determines the year of the [Worldwide Box Office](https://www.boxofficemojo.com/year/world/) to pull.
|
||||||
|
|
||||||
|
**Allowed Values:** Number between 1977 and the current year, `current`, or relative current (`current-#`; where
|
||||||
|
`#` is the number of year before the current)
|
||||||
|
|
||||||
|
??? blank "`limit` - The maximum number of result to return"
|
||||||
|
|
||||||
|
This determines the maximum number of results to return. If there are less results then the limit then all will
|
||||||
|
be returned.
|
||||||
|
|
||||||
|
**Default Value:** Returns all results
|
||||||
|
|
||||||
|
**Allowed Values:** Number greter than 0
|
||||||
|
|
||||||
|
???+ example "Example"
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
collections:
|
||||||
|
|
||||||
|
Current Worlwide Box Office:
|
||||||
|
mojo_world:
|
||||||
|
year: current
|
||||||
|
|
||||||
|
Last Year's Worlwide Box Office:
|
||||||
|
mojo_world:
|
||||||
|
year: current-1
|
||||||
|
|
||||||
|
2020 Top 10 Worlwide Box Office:
|
||||||
|
mojo_world:
|
||||||
|
year: 2020
|
||||||
|
limit: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
??? blank "`mojo_all_time` - Uses the All Time Lists.<a class="headerlink" href="#mojo-all-time" title="Permanent link">¶</a>"
|
||||||
|
|
||||||
|
<div id="mojo-all-time" />Uses the [All Time Lists](https://www.boxofficemojo.com/charts/overall/) to collection items.
|
||||||
|
|
||||||
|
<hr style="margin: 0px;">
|
||||||
|
|
||||||
|
**Works With:** Movies, Playlists, and Custom Sort
|
||||||
|
|
||||||
|
**Builder Attribute:** `mojo_all_time`
|
||||||
|
|
||||||
|
**Builder Value:** [Dictionary](../../pmm/yaml.md#dictionaries) of Attributes
|
||||||
|
|
||||||
|
??? blank "`chart` - Determines the chart you want to use"
|
||||||
|
|
||||||
|
Determines the chart you want to use.
|
||||||
|
|
||||||
|
**Allowed Values:** `domestic` or `worldwide`
|
||||||
|
|
||||||
|
??? blank "`content_rating_filter` - Determines the content rating chart to use"
|
||||||
|
|
||||||
|
Determines the content rating chart to use.
|
||||||
|
|
||||||
|
**Allowed Values:** `g`, `g/pg`, `pg`, `pg-13`, `r` or `nc-17`
|
||||||
|
|
||||||
|
??? blank "`limit` - The maximum number of result to return"
|
||||||
|
|
||||||
|
This determines the maximum number of results to return. If there are less results then the limit then all will
|
||||||
|
be returned.
|
||||||
|
|
||||||
|
**Default Value:** Returns all results
|
||||||
|
|
||||||
|
**Allowed Values:** Number greter than 0
|
||||||
|
|
||||||
|
???+ example "Example"
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
collections:
|
||||||
|
|
||||||
|
Top 100 Domestic All Time Grosses:
|
||||||
|
mojo_all_time:
|
||||||
|
chart: domestic
|
||||||
|
limit: 100
|
||||||
|
|
||||||
|
Top 100 Worldwide All Time Grosses:
|
||||||
|
mojo_all_time:
|
||||||
|
chart: worldwide
|
||||||
|
limit: 100
|
||||||
|
|
||||||
|
Top 10 Domestic All Time G Movie Grosses:
|
||||||
|
mojo_world:
|
||||||
|
chart: domestic
|
||||||
|
content_rating_filter: g
|
||||||
|
limit: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
??? blank "`mojo_never` - Uses the Never Hit Lists.<a class="headerlink" href="#mojo-never" title="Permanent link">¶</a>"
|
||||||
|
|
||||||
|
<div id="mojo-never" />Uses the [Never Hit Lists](https://www.boxofficemojo.com/charts/overall/) (Bottom Section) to
|
||||||
|
collection items.
|
||||||
|
|
||||||
|
<hr style="margin: 0px;">
|
||||||
|
|
||||||
|
**Works With:** Movies, Playlists, and Custom Sort
|
||||||
|
|
||||||
|
**Builder Attribute:** `mojo_never`
|
||||||
|
|
||||||
|
**Builder Value:** [Dictionary](../../pmm/yaml.md#dictionaries) of Attributes
|
||||||
|
|
||||||
|
??? blank "`chart` - Determines the chart you want to use"
|
||||||
|
|
||||||
|
Determines the chart you want to use.
|
||||||
|
|
||||||
|
**Allowed Values:** Item in the drop down found [here](https://www.boxofficemojo.com/charts/overall/)
|
||||||
|
|
||||||
|
??? blank "`never` - Determines the never filter to use"
|
||||||
|
|
||||||
|
Determines the never filter to use.
|
||||||
|
|
||||||
|
**Default Value:** `1`
|
||||||
|
|
||||||
|
**Allowed Values:** `1`, `5`, or `10`
|
||||||
|
|
||||||
|
??? blank "`limit` - The maximum number of result to return"
|
||||||
|
|
||||||
|
This determines the maximum number of results to return. If there are less results then the limit then all will
|
||||||
|
be returned.
|
||||||
|
|
||||||
|
**Default Value:** Returns all results
|
||||||
|
|
||||||
|
**Allowed Values:** Number greter than 0
|
||||||
|
|
||||||
|
???+ example "Example"
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
collections:
|
||||||
|
|
||||||
|
Top 100 Domestic Never #1:
|
||||||
|
mojo_never:
|
||||||
|
chart: domestic
|
||||||
|
limit: 100
|
||||||
|
|
||||||
|
Top 100 Domestic Never #10:
|
||||||
|
mojo_never:
|
||||||
|
chart: domestic
|
||||||
|
never: 10
|
||||||
|
limit: 100
|
||||||
|
|
||||||
|
Top 100 German Never #1:
|
||||||
|
mojo_never:
|
||||||
|
chart: germany
|
||||||
|
limit: 100
|
||||||
|
```
|
||||||
|
|
||||||
|
??? blank "`mojo_record` - Uses other Record Lists.<a class="headerlink" href="#mojo-record" title="Permanent link">¶</a>"
|
||||||
|
|
||||||
|
<div id="mojo-record" />Uses the [Weekend Records](https://www.boxofficemojo.com/charts/weekend/),
|
||||||
|
[Daily Records](https://www.boxofficemojo.com/charts/daily/), and
|
||||||
|
[Miscellaneous Records](https://www.boxofficemojo.com/charts/misc/) to collection items.
|
||||||
|
|
||||||
|
<hr style="margin: 0px;">
|
||||||
|
|
||||||
|
**Works With:** Movies, Playlists, and Custom Sort
|
||||||
|
|
||||||
|
**Builder Attribute:** `mojo_record`
|
||||||
|
|
||||||
|
**Builder Value:** [Dictionary](../../pmm/yaml.md#dictionaries) of Attributes
|
||||||
|
|
||||||
|
??? blank "`chart` - Determines the record you want to use"
|
||||||
|
|
||||||
|
Determines the chart you want to use.
|
||||||
|
|
||||||
|
**Allowed Values:** `second_weekend_drop`, `post_thanksgiving_weekend_drop`, `top_opening_weekend`,
|
||||||
|
`worst_opening_weekend_theater_avg`, `mlk_opening`, `easter_opening`, `memorial_opening`, `labor_opening`,
|
||||||
|
`president_opening`, `thanksgiving_3_opening`, `thanksgiving_5_opening`, `mlk`, `easter`, `4th`, `memorial`,
|
||||||
|
`labor`, `president`, `thanksgiving_3`, `thanksgiving_5`, `january`, `february`, `march`, `april`, `may`,
|
||||||
|
`june`, `july`, `august`, `september`, `october`, `november`, `december`, `spring`, `summer`, `fall`,
|
||||||
|
`holiday_season`, `winter`, `g`, `g/pg`, `pg`, `pg-13`, `r`, `nc-17`, `top_opening_weekend_theater_avg_all`,
|
||||||
|
`top_opening_weekend_theater_avg_wide`, `opening_day`, `single_day_grosses`, `christmas_day_gross`,
|
||||||
|
`new_years_day_gross`, `friday`, `saturday`, `sunday`, `monday`, `tuesday`, `wednesday`, `thursday`,
|
||||||
|
`friday_non_opening`, `saturday_non_opening`, `sunday_non_opening`, `monday_non_opening`, `tuesday_non_opening`,
|
||||||
|
`wednesday_non_opening`, `thursday_non_opening`, `biggest_theater_drop`, or `opening_week`
|
||||||
|
|
||||||
|
|
||||||
|
??? blank "`limit` - The maximum number of result to return"
|
||||||
|
|
||||||
|
This determines the maximum number of results to return. If there are less results then the limit then all will
|
||||||
|
be returned.
|
||||||
|
|
||||||
|
**Default Value:** Returns all results
|
||||||
|
|
||||||
|
**Allowed Values:** Number greter than 0
|
||||||
|
|
||||||
|
???+ example "Example"
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
collections:
|
||||||
|
|
||||||
|
Top 10 Biggest Opening Weekends:
|
||||||
|
mojo_record:
|
||||||
|
chart: top_opening_weekend
|
||||||
|
limit: 10
|
||||||
|
|
||||||
|
Top 10 Biggest Opening Day:
|
||||||
|
mojo_record:
|
||||||
|
chart: opening_day
|
||||||
|
limit: 10
|
||||||
|
|
||||||
|
Top 10 Biggest Opening Weeks:
|
||||||
|
mojo_record:
|
||||||
|
chart: opening_week
|
||||||
|
limit: 10
|
||||||
|
```
|
@ -0,0 +1,273 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
from modules import util
|
||||||
|
from modules.util import Failed
|
||||||
|
from num2words import num2words
|
||||||
|
from urllib.parse import urlparse, parse_qs
|
||||||
|
|
||||||
|
logger = util.logger
|
||||||
|
|
||||||
|
builders = ["mojo_world", "mojo_domestic", "mojo_international", "mojo_record", "mojo_all_time", "mojo_never"]
|
||||||
|
top_options = {
|
||||||
|
"second_weekend_drop": ("Biggest Second Weekend Drops", "/chart/biggest_second_weekend_gross_drop/", None),
|
||||||
|
"post_thanksgiving_weekend_drop": ("Largest Post-Thanksgiving Weekend Drops", "/chart/post_thanksgiving_weekend_drop/", None),
|
||||||
|
"top_opening_weekend": ("Top Opening Weekends", "/chart/top_opening_weekend/", None),
|
||||||
|
"worst_opening_weekend_theater_avg": ("Worst Opening Weekend Per-Theater Averages", "/chart/btm_wide_opening_weekend_theater_avg/", None),
|
||||||
|
"top_opening_weekend_theater_avg_all": ("Top Opening Theater Averages", "/chart/top_opening_weekend_theater_avg/", {"by_release_scale": "all"}),
|
||||||
|
"top_opening_weekend_theater_avg_wide": ("Top Wide Opening Theater Averages", "/chart/top_opening_weekend_theater_avg/", {"by_release_scale": "wide"}),
|
||||||
|
"january": ("Top Opening Weekend in January", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "january"}),
|
||||||
|
"february": ("Top Opening Weekend in February", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "february"}),
|
||||||
|
"march": ("Top Opening Weekend in March", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "march"}),
|
||||||
|
"april": ("Top Opening Weekend in April", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "april"}),
|
||||||
|
"may": ("Top Opening Weekend in May", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "may"}),
|
||||||
|
"june": ("Top Opening Weekend in June", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "june"}),
|
||||||
|
"july": ("Top Opening Weekend in July", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "july"}),
|
||||||
|
"august": ("Top Opening Weekend in August", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "august"}),
|
||||||
|
"september": ("Top Opening Weekend in September", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "september"}),
|
||||||
|
"october": ("Top Opening Weekend in October", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "october"}),
|
||||||
|
"november": ("Top Opening Weekend in November", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "november"}),
|
||||||
|
"december": ("Top Opening Weekend in December", "/chart/release_top_opn_wkd_in_month/", {"in_occasion": "december"}),
|
||||||
|
"spring": ("Top Opening Weekend in Spring", "/chart/release_top_opn_wkd_in_season/", {"in_occasion": "spring"}),
|
||||||
|
"summer": ("Top Opening Weekend in Summer", "/chart/release_top_opn_wkd_in_season/", {"in_occasion": "summer"}),
|
||||||
|
"fall": ("Top Opening Weekend in Fall", "/chart/release_top_opn_wkd_in_season/", {"in_occasion": "fall"}),
|
||||||
|
"holiday_season": ("Top Opening Weekend in The Holiday Season", "/chart/release_top_opn_wkd_in_season/", {"in_occasion": "holiday_season"}),
|
||||||
|
"winter": ("Top Opening Weekend in Winter", "/chart/release_top_opn_wkd_in_season/", {"in_occasion": "winter"}),
|
||||||
|
"g": ("Top Opening Weekend for G Ratings", "/chart/top_opening_wknd_by_mpaa/", {"by_mpaa": "G"}),
|
||||||
|
"g/pg": ("Top Opening Weekend for G/PG Ratings", "/chart/top_opening_wknd_by_mpaa/", {"by_mpaa": "G%2FPG"}),
|
||||||
|
"pg": ("Top Opening Weekend for PG Ratings", "/chart/top_opening_wknd_by_mpaa/", {"by_mpaa": "PG"}),
|
||||||
|
"pg-13": ("Top Opening Weekend for PG-13 Ratings", "/chart/top_opening_wknd_by_mpaa/", {"by_mpaa": "PG-13"}),
|
||||||
|
"r": ("Top Opening Weekend for R Ratings", "/chart/top_opening_wknd_by_mpaa/", {"by_mpaa": "R"}),
|
||||||
|
"nc-17": ("Top Opening Weekend for NC-17 Ratings", "/chart/top_opening_wknd_by_mpaa/", {"by_mpaa": "NC-17"}),
|
||||||
|
"mlk": ("Top Weekend for MLK Day", "/chart/release_top_weekend_gross/", {"by_occasion", "us_mlkday_weekend"}),
|
||||||
|
"easter": ("Top Weekend for Easter", "/chart/release_top_weekend_gross/", {"by_occasion", "easter_weekend"}),
|
||||||
|
"4th": ("Top Weekend for the 4th of July", "/chart/release_top_weekend_gross/", {"by_occasion", "us_july4_weekend"}),
|
||||||
|
"memorial": ("Top Weekend for Memorial Day", "/chart/release_top_weekend_gross/", {"by_occasion", "us_memorialday_weekend"}),
|
||||||
|
"labor": ("Top Weekend for Labor Day", "/chart/release_top_weekend_gross/", {"by_occasion", "us_laborday_weekend"}),
|
||||||
|
"president": ("Top Weekend for President's Day", "/chart/release_top_weekend_gross/", {"by_occasion", "us_presidentsday_weekend"}),
|
||||||
|
"thanksgiving_3": ("Top 3 Day Weekend for Thanksgiving", "/chart/release_top_weekend_gross/", {"by_occasion", "us_thanksgiving_3"}),
|
||||||
|
"thanksgiving_5": ("Top 5 Day Weekend for Thanksgiving", "/chart/release_top_weekend_gross/", {"by_occasion", "us_thanksgiving_5"}),
|
||||||
|
"mlk_opening": ("Top Opening Weekend for MLK Day", "/chart/top_opening_holiday_weekends/", {"by_occasion", "us_mlkday_weekend"}),
|
||||||
|
"easter_opening": ("Top Opening Weekend for Easter", "/chart/top_opening_holiday_weekends/", {"by_occasion", "easter_weekend"}),
|
||||||
|
"memorial_opening": ("Top Opening Weekend for Memorial Day", "/chart/top_opening_holiday_weekends/", {"by_occasion", "us_memorialday_weekend"}),
|
||||||
|
"labor_opening": ("Top Opening Weekend for Labor Day", "/chart/top_opening_holiday_weekends/", {"by_occasion", "us_laborday_weekend"}),
|
||||||
|
"president_opening": ("Top Opening Weekend for MLK Day", "/chart/top_opening_holiday_weekends/", {"by_occasion", "us_presidentsday_weekend"}),
|
||||||
|
"thanksgiving_3_opening": ("Top 3 Day Opening Weekend for Thanksgiving", "/chart/top_thanksgiving_openings/", {"by_occasion", "us_thanksgiving_3"}),
|
||||||
|
"thanksgiving_5_opening": ("Top 5 Day Opening Weekend for Thanksgiving", "/chart/top_thanksgiving_openings/", {"by_occasion", "us_thanksgiving_5"}),
|
||||||
|
"opening_week": ("Top Opening Week", "/chart/top_opening_week/", None),
|
||||||
|
"biggest_theater_drop": ("Biggest Theater Drops", "/chart/biggest_third_weekend_num_theaters_drop/", None),
|
||||||
|
"opening_day": ("Top Opening Day", "/chart/top_opening_day/", None),
|
||||||
|
"single_day_grosses": ("Top Day", "/chart/release_top_daily_gross/", None),
|
||||||
|
"christmas_day_gross": ("Top Christmas Day", "/chart/release_top_holiday_gross/", {"by_occasion": "christmas_day"}),
|
||||||
|
"new_years_day_gross": ("Top New Years Day", "/chart/release_top_holiday_gross/", {"by_occasion": "newyearsday"}),
|
||||||
|
"friday": ("Top Friday", "/chart/release_top_daily_gross_by_dow/", {"by_occasion": "friday"}),
|
||||||
|
"saturday": ("Top Saturday", "/chart/release_top_daily_gross_by_dow/", {"by_occasion": "saturday"}),
|
||||||
|
"sunday": ("Top Sunday", "/chart/release_top_daily_gross_by_dow/", {"by_occasion": "sunday"}),
|
||||||
|
"monday": ("Top Monday", "/chart/release_top_daily_gross_by_dow/", {"by_occasion": "monday"}),
|
||||||
|
"tuesday": ("Top Tuesday", "/chart/release_top_daily_gross_by_dow/", {"by_occasion": "tuesday"}),
|
||||||
|
"wednesday": ("Top Wednesday", "/chart/release_top_daily_gross_by_dow/", {"by_occasion": "wednesday"}),
|
||||||
|
"thursday": ("Top Thursday", "/chart/release_top_daily_gross_by_dow/", {"by_occasion": "thursday"}),
|
||||||
|
"friday_non_opening": ("Top Friday Non-Opening", "/chart/top_non_opening_by_dow/", {"by_occasion": "friday"}),
|
||||||
|
"saturday_non_opening": ("Top Saturday Non-Opening", "/chart/top_non_opening_by_dow/", {"by_occasion": "saturday"}),
|
||||||
|
"sunday_non_opening": ("Top Sunday Non-Opening", "/chart/top_non_opening_by_dow/", {"by_occasion": "sunday"}),
|
||||||
|
"monday_non_opening": ("Top Monday Non-Opening", "/chart/top_non_opening_by_dow/", {"by_occasion": "monday"}),
|
||||||
|
"tuesday_non_opening": ("Top Tuesday Non-Opening", "/chart/top_non_opening_by_dow/", {"by_occasion": "tuesday"}),
|
||||||
|
"wednesday_non_opening": ("Top Wednesday Non-Opening", "/chart/top_non_opening_by_dow/", {"by_occasion": "wednesday"}),
|
||||||
|
"thursday_non_opening": ("Top Thursday Non-Opening", "/chart/top_non_opening_by_dow/", {"by_occasion": "thursday"}),
|
||||||
|
}
|
||||||
|
chart_options = ["domestic", "worldwide"]
|
||||||
|
content_rating_options = {
|
||||||
|
"g": "G",
|
||||||
|
"g/pg": "G%2FPG",
|
||||||
|
"pg": "PG",
|
||||||
|
"pg-13": "PG-13",
|
||||||
|
"r": "R",
|
||||||
|
"nc-17": "NC-17",
|
||||||
|
}
|
||||||
|
never_in_options = {
|
||||||
|
"1": ("#1", "never_1"),
|
||||||
|
"5": ("the Top 5", "never_5"),
|
||||||
|
"10": ("the Top 10", "never_10"),
|
||||||
|
}
|
||||||
|
intl_range_options = ["weekend", "monthly", "quarterly", "yearly"]
|
||||||
|
dome_range_options = intl_range_options + ["daily", "weekly", "season", "holiday"]
|
||||||
|
year_options = ["current"] + [str(t) for t in range(1977, datetime.now().year + 1)]
|
||||||
|
quarter_options = ["current", "q1", "q2", "q3", "q4"]
|
||||||
|
quarters = {1: "q1", 2: "q1", 3: "q1", 4: "q2", 5: "q2", 6: "q2", 7: "q3", 8: "q3", 9: "q3", 10: "q4", 11: "q4", 12: "q4"}
|
||||||
|
season_options = ["current", "winter", "spring", "summer", "fall", "holiday"]
|
||||||
|
seasons = {1: "winter", 2: "winter", 3: "spring", 4: "spring", 5: "summer", 6: "summer", 7: "summer", 8: "summer", 9: "fall", 10: "fall", 11: "holiday", 12: "holiday"}
|
||||||
|
holiday_options = {
|
||||||
|
"new_years_day": ("New Year's Day", "newyearsday"),
|
||||||
|
"new_year_weekend": ("New Year Weekend", "us_newyear_weekend"),
|
||||||
|
"mlk_day": ("MLK Day", "us_mlkday"),
|
||||||
|
"mlk_day_weekend": ("MLK Day Weekend", "us_mlkday_weekend"),
|
||||||
|
"presidents_day": ("President's Day", "us_presidentsday"),
|
||||||
|
"presidents_day_weekend": ("President's Day Weekend", "us_presidentsday_weekend"),
|
||||||
|
"easter": ("Easter", "easter_sunday"),
|
||||||
|
"easter_weekend": ("Easter Weekend", "easter_weekend"),
|
||||||
|
"memorial_day": ("Memorial Day", "us_memorialday"),
|
||||||
|
"memorial_day_weekend": ("Memorial Day Weekend", "us_memorialday_weekend"),
|
||||||
|
"independence_day": ("Independence Day", "us_july4"),
|
||||||
|
"independence_day_weekend": ("Independence Day Weekend", "us_july4_weekend"),
|
||||||
|
"labor_day": ("Labor Day", "us_laborday"),
|
||||||
|
"labor_day_weekend": ("Labor Day Weekend", "us_laborday_weekend"),
|
||||||
|
"indigenous_day": ("Indigenous People's Day", "us_indig_peoples_day"),
|
||||||
|
"indigenous_day_weekend": ("", "us_indig_peoples_day_weekend"),
|
||||||
|
"halloween": ("Halloween", "halloween"),
|
||||||
|
"thanksgiving": ("Thanksgiving", "us_thanksgiving"),
|
||||||
|
"thanksgiving_3": ("Thanksgiving Weekend", "us_thanksgiving_3"),
|
||||||
|
"thanksgiving_4": ("Thanksgiving 4-Day Weekend", "us_thanksgiving_4"),
|
||||||
|
"thanksgiving_5": ("Thanksgiving 5-Day Weekend", "us_thanksgiving_5"),
|
||||||
|
"post_thanksgiving_weekend": ("Post-Thanksgiving Weekend", "us_post_thanksgiving_weekend"),
|
||||||
|
"christmas_day": ("Christmas Day", "christmas_day"),
|
||||||
|
"christmas_weekend": ("Christmas Weekend", "us_christmas_weekend"),
|
||||||
|
"new_years_eve": ("New Year's Eve", "newyearseve")
|
||||||
|
}
|
||||||
|
base_url = "https://www.boxofficemojo.com"
|
||||||
|
|
||||||
|
|
||||||
|
class BoxOfficeMojo:
|
||||||
|
def __init__(self, config):
|
||||||
|
self.config = config
|
||||||
|
self._never_options = None
|
||||||
|
self._intl_options = None
|
||||||
|
self._year_options = None
|
||||||
|
|
||||||
|
def _options(self, url, nav_type="area"):
|
||||||
|
output = {}
|
||||||
|
options = self._request(url, xpath=f"//select[@id='{nav_type}-navSelector']/option")
|
||||||
|
for option in options:
|
||||||
|
query = parse_qs(urlparse(option.xpath("@value")[0]).query)
|
||||||
|
output[option.xpath("text()")[0].lower()] = query["area"][0] if "area" in query else ""
|
||||||
|
return output
|
||||||
|
|
||||||
|
@property
|
||||||
|
def never_options(self):
|
||||||
|
if self._never_options is None:
|
||||||
|
self._never_options = self._options("/chart/never_in_top/")
|
||||||
|
return self._never_options
|
||||||
|
|
||||||
|
@property
|
||||||
|
def intl_options(self):
|
||||||
|
if self._intl_options is None:
|
||||||
|
self._intl_options = self._options("/intl/")
|
||||||
|
return self._intl_options
|
||||||
|
|
||||||
|
@property
|
||||||
|
def year_options(self):
|
||||||
|
if self._year_options is None:
|
||||||
|
self._year_options = [y for y in self._options("/year/world/", nav_type="year")]
|
||||||
|
return self._year_options
|
||||||
|
|
||||||
|
def _request(self, url, xpath=None, params=None):
|
||||||
|
logger.trace(f"URL: {base_url}{url}")
|
||||||
|
if params:
|
||||||
|
logger.trace(f"Params: {params}")
|
||||||
|
response = self.config.get_html(f"{base_url}{url}", headers=util.header(), params=params)
|
||||||
|
return response.xpath(xpath) if xpath else response
|
||||||
|
|
||||||
|
def _parse_list(self, url, params, limit):
|
||||||
|
response = self._request(url, params=params)
|
||||||
|
total_html = response.xpath("//li[contains(@class, 'mojo-pagination-button-center')]/a/text()")
|
||||||
|
total = int(total_html[0].replace(",", "").split(" ")[2]) if total_html else 0
|
||||||
|
if total and (limit < 1 or total < limit):
|
||||||
|
limit = total
|
||||||
|
pages = int((limit - 1) / 200) + 1 if total else 0
|
||||||
|
for field_name in ["release ", "title", "release_group"]:
|
||||||
|
output = response.xpath(f"//td[contains(@class, 'mojo-field-type-{field_name}')]/a/@href")
|
||||||
|
if output:
|
||||||
|
break
|
||||||
|
for i in range(1, pages):
|
||||||
|
response = self._request(url, params={"offset": 200 * i})
|
||||||
|
output.extend(response.xpath(f"//td[contains(@class, 'mojo-field-type-{field_name}')]/a/@href"))
|
||||||
|
if not limit or len(output) < limit:
|
||||||
|
limit = len(output)
|
||||||
|
return [i[:i.index("?")] for i in output[:limit]]
|
||||||
|
|
||||||
|
def _imdb(self, url):
|
||||||
|
response = self._request(url)
|
||||||
|
imdb_url = response.xpath("//select[@id='releasegroup-picker-navSelector']/option[text()='All Releases']/@value")
|
||||||
|
if not imdb_url:
|
||||||
|
raise Failed(f"Mojo Error: IMDb ID not found at {base_url}{url}")
|
||||||
|
return imdb_url[0][7:-1]
|
||||||
|
|
||||||
|
def get_imdb_ids(self, method, data):
|
||||||
|
params = None
|
||||||
|
if method == "mojo_record":
|
||||||
|
text, url, params = top_options[data["chart"]]
|
||||||
|
elif method == "mojo_world":
|
||||||
|
text = f"{data['year']} Worldwide Box Office"
|
||||||
|
url = f"/year/world/{data['year']}/"
|
||||||
|
elif method == "mojo_all_time":
|
||||||
|
text = f"Top Lifetime {data['chart'].capitalize()}"
|
||||||
|
if data["content_rating_filter"] is None:
|
||||||
|
url = "/chart/top_lifetime_gross/" if data["chart"] == "domestic" else "/chart/ww_top_lifetime_gross/"
|
||||||
|
else:
|
||||||
|
text += f" {data['content_rating_filter'].upper()}"
|
||||||
|
url = f"/chart/mpaa_title_lifetime_gross/"
|
||||||
|
params = {"by_mpaa": content_rating_options[data['content_rating_filter']]}
|
||||||
|
text += " Grosses"
|
||||||
|
elif method == "mojo_never":
|
||||||
|
pretty, arg_key = never_in_options[data["never"]]
|
||||||
|
text = f"Top-Grossing Movies That Never Hit {pretty} {data['chart'].capitalize()}"
|
||||||
|
url = f"/chart/never_in_top/"
|
||||||
|
params = {"by_rank_threshold": data["never"]}
|
||||||
|
if data["chart"] != "domestic":
|
||||||
|
params["area"] = self.never_options[data["chart"]]
|
||||||
|
else:
|
||||||
|
chart = data["chart"].capitalize() if "chart" in data else "Domestic"
|
||||||
|
|
||||||
|
if data["range"] == "daily":
|
||||||
|
day = datetime.strptime(data["range_data"], "%Y-%m-%d")
|
||||||
|
day = day.strftime("%b {th}, %Y").replace("{th}", num2words(day.day, to='ordinal_num'))
|
||||||
|
chart_title = f"{day}"
|
||||||
|
url = f"/date/{data['range_data']}/"
|
||||||
|
elif data["range"] == "weekend":
|
||||||
|
chart_title = f"Weekend {data['range_data']} {data['year']}"
|
||||||
|
url = f"/weekend/{data['year']}W{data['range_data']:02}/"
|
||||||
|
elif data["range"] == "weekly":
|
||||||
|
chart_title = f"Week {data['range_data']} {data['year']}"
|
||||||
|
url = f"/weekly/{data['year']}W{data['range_data']:02}/"
|
||||||
|
elif data["range"] == "monthly":
|
||||||
|
chart_title = f"{data['range_data'].capitalize()} {data['year']}"
|
||||||
|
url = f"/month/{data['range_data']}/{data['year']}/"
|
||||||
|
elif data["range"] == "quarterly":
|
||||||
|
chart_title = f"{data['range_data'].capitalize()} {data['year']}"
|
||||||
|
url = f"/quarter/{data['range_data']}/{data['year']}/"
|
||||||
|
elif data["range"] == "season":
|
||||||
|
chart_title = f"{data['range_data'].capitalize()} {data['year']}"
|
||||||
|
url = f"/season/{data['range_data']}/{data['year']}/"
|
||||||
|
elif data["range"] == "holiday":
|
||||||
|
title, slug = holiday_options[data["range_data"]]
|
||||||
|
chart_title = f"{title} {data['year']}"
|
||||||
|
url = f"/holiday/{slug}/{data['year']}/"
|
||||||
|
else:
|
||||||
|
chart_title = f"{data['year']}"
|
||||||
|
url = f"/year/{data['year']}/"
|
||||||
|
text = f"{chart} Box Office For {chart_title}"
|
||||||
|
if data["limit"]:
|
||||||
|
text += f" ({data['limit']})"
|
||||||
|
logger.info(f"Processing {method.replace('_', ' ').title()}: {text}")
|
||||||
|
items = self._parse_list(url, params, data["limit"])
|
||||||
|
if not items:
|
||||||
|
raise Failed(f"Mojo Error: No List Items found in {method}: {data}")
|
||||||
|
ids = []
|
||||||
|
total_items = len(items)
|
||||||
|
for i, item in enumerate(items, 1):
|
||||||
|
logger.ghost(f"Finding IMDb ID {i}/{total_items}")
|
||||||
|
if "title" in item:
|
||||||
|
imdb_id = item[7:-1]
|
||||||
|
else:
|
||||||
|
imdb_id = None
|
||||||
|
expired = None
|
||||||
|
if self.config.Cache:
|
||||||
|
imdb_id, expired = self.config.Cache.query_letterboxd_map(item)
|
||||||
|
if not imdb_id or expired is not False:
|
||||||
|
try:
|
||||||
|
imdb_id = self._imdb(item)
|
||||||
|
except Failed as e:
|
||||||
|
logger.error(e)
|
||||||
|
continue
|
||||||
|
if self.config.Cache:
|
||||||
|
self.config.Cache.update_letterboxd_map(expired, item, imdb_id)
|
||||||
|
ids.append((imdb_id, "imdb"))
|
||||||
|
logger.info(f"Processed {total_items} IMDb IDs")
|
||||||
|
return ids
|
Loading…
Reference in new issue