(*************************************************** Ant Movie Catalog importation script www.antp.be/software/moviecatalog/ [Infos] Authors=J Title=IMDB (Actor images) Description=Import of multiple actors: name, character, image and personal page referrer from IMDB. See options for details. Site=us.imdb.com Language=EN Version=1.3.6 - 21/07/2023 Requires=4.2.2 Comments=Use this script to fill your extra data with actor pictures, names, character names and links from IMDB.|This script uses parts of original IMDB script v3.80||Image importation method is set in the AMC preferences!||V 1.0.1|- Changed to UTF8 title search|- Fix for picture link||V 1.1 (The somehow lost version)|- Batch mode integrated|- Special characters are now correctly shown|- Script now tries to detect a different movie when replacing pictures and adds five additional pictures instead of replacing||V1.2|- Added possibility to select number of actors for import|- Added option to exchange selected actor(s)|- Added option for image demand||V1.2.1|- Added used movie URL in first actors comments|- Script deletes actors name from role "(as ...)"||V1.2.2|- Added connection error handling||V1.2.3|- Added option for title search||V1.2.4|- Fix for new structure||V1.3|- Adaption to new IMDB page structure License=This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GetInfo=1 RequiresMovies=1 [Options] ExactTitle=1|0|0=Popular Search|1=Exact title is needed BatchMode=0|0|0=Normal working mode, prompts user when needed|1=Does not display any window, takes the first movie found|2=Same as 1, but it uses the URL field if available to update movie information SelectionMode=0|0|0=ADD images (Standard)|1=REPLACE selected images|2=EXCHANGE actors NumberOfActors=0|1|0=choose ONE actor|1=first FIVE actors|2=first TEN actors ActorImage=0|0|0=No actor image needed|1=Import only actors with image ImageLayout=2|2|0=Original uncut image (huge!)|1=Image from movie page (fast)|2=Image from actor page (slow) [Parameters] ***************************************************) program IMDB_Actor_images; //Default: ET 0, BM 0, SM 0, NOA 1, AI 0, IL 2 uses StringUtils1; const PopularTitleSearchURL = 'https://www.imdb.com/find?s=tt&q='; ExactTitleSearchURL = 'https://www.imdb.com/find?s=tt&exact=true&q='; var MovieName, ErrorMessage: string; // ***** analyzes IMDB's results page that asks to select a movie from a list ***** procedure AnalyzeResultsPage(Address: string); var PageText: string; Value: string; begin PageText := GetPage(Address); if PageText = '' Then SetStatic(ErrorMessage, GetStatic(ErrorMessage) + 'Page Error at #' + GetField(fnumber) + ' - ' + GetField(fOriginalTitle) + #13#10); //**** ERROR Handling **** if pos('Find - IMDb', PageText) = 0 then AnalyzeMoviePage(PageText) else begin if Pos('<b>No Matches.</b>', PageText) > 0 then begin if GetOption('BatchMode') = 0 then ShowMessage('No movie found for this search.'); Exit; end; if GetOption('BatchMode') = 0 then begin PickTreeClear; Value := TextBetween(PageText, '>Titles</h3>', '</section>'); if Value <> '' then begin PickTreeAdd('Titles search results for: "' + URLDecode(MovieName) + '"', ''); // adds movie name to search title AddMovieTitles(Value); end; if PickTreeExec(Address) then AnalyzeResultsPage(Address); end else if (MovieYear <> '') then begin Value := GetUrlBefore(PageText, '(' + MovieYear + ')', ''); if Value = '' then begin Value := GetUrlBefore(PageText, '(' + IntToStr(StrToInt(MovieYear, 0) - 1) + ')', ''); if Value = '' then Value := GetUrlBefore(PageText, '(' + IntToStr(StrToInt(MovieYear, 0) + 1) + ')', ''); end; if Value <> '' then AnalyzeResultsPage('https://www.imdb.com' + Value); end else begin Value := TextBetween(PageText, '<td class="primary_photo">', '<img src'); if Value <> '' then AnalyzeResultsPage('https://www.imdb.com' + TextBetween(Value, '<a href="', '"')); end; end; end; // ***** adds the movie titles found on IMDB's results page ***** function AddMovieTitles(List: string): Boolean; var Value, Value1: string; Address: string; begin Result := False; Value := TextBetween(List, '<td class="result_text">', '</td>'); if Value = '' then Value := TextBetween(List, '<div class="ipc-metadata-list-summary-item__c">', '</div></div>'); Value := StringReplace(Value, 'aka', ' | aka'); List := RemainingText; while Value <> '' do begin Address := TextBetween(Value, '<a href="/title/tt', '/'); if Address = '' then Address := TextBetween(Value, '<a class="ipc-metadata-list-summary-item__t" role="button" tabindex="0" aria-disabled="false" href="/title/tt', '/'); // Address := Address + '/reference'; // not needed here Value := StringReplace(Value, '"false">', '"false"> ¦ '); // basic formatting HTMLRemoveTags(Value); Value1 := TextBefore(Value, ' ¦', '') + ' (' + TextAfter(Value, '¦ '); // more formatting If Pos('¦', Value1) > 0 then Value := TextBefore(Value1, ' ¦', '') + ') ¦ ' + TextAfter(Value1, '¦ '); // more formatting Value := UTF8Decode(Value); HTMLDecode(Value); PickTreeAdd(Value, 'https://www.imdb.com/title/tt' + Address); Result := True; Value := TextBetween(List, '<td class="result_text">', '</td>'); if value = '' then Value := TextBetween(List, '<div class="ipc-metadata-list-summary-item__c">', '</div></div>'); Value := StringReplace(Value, 'aka', ' | aka'); List := RemainingText; end; end; // ***** analyzes the page containing actors information ***** procedure AnalyzeMoviePage(PageText: string); var Value, Value2, Value3 : string; index, count, maxactor : Integer; begin Value := UTF8Decode(TextBetween(PageText, 'ipc-media--avatar', 'ipc-metadata-list')); Value := TextAfter(Value, 'style="width:100%">'); case GetOption('SelectionMode') of 1: // Replace images begin index := GetExtraCount; for count := 0 to index - 1 do begin if (GetExtraField(count, eCategory) = 'Actors') and (IsExtraSelected(count) = TRUE) then begin Value3 := GetExtraField(count, eURL); if POS(Value3, Value) = 0 then //Wrong movie? --> 5 new pictures begin SetOption('SelectionMode', 0); SetOption('NumberOfActors', 1); AnalyzeMoviePage(PageText); SetOption('SelectionMode', 1); exit; end; Value2 := TextBefore(Value, Value3, '100%">'); If Value2 = '' Then Value2 := TextBefore(Value, Value3, ''); // Otherwise pic from first actor is not changed Value2 := TextBetween(Value2, '140w, ', ' 210w'); if Value2 <> '' then GetActorImage(Value2, Value3, count); // "if" because of intentionally senseless case: replace of an empty picture gives picture ERROR message at end end; end; end; 0: // Get new images begin if Value = '' then exit; count := GetOption('NumberOfActors') * 5; maxactor := count; if GetOption('NumberOfActors') = 0 then // choose one begin GetActorList(Value); // PickTree with actors index := AddExtra; PickTreeTitle('Please choose an actor :'); if PickTreeExec(Value) then GetActor(Value, index); end else while count > 0 do // get first 5,10 begin if POS('/name/', Value) = 0 then exit; index := AddExtra; Value2 := TextBefore(Value, 'style="width:100%">',''); If Value2 = '' then Value2 := Value; GetActor(Value2, index); Value := TextAfter(Value, 'style="width:100%">'); if count = maxactor then SetExtraField(index, eComments, 'Actor pictures from movie: ' + #13#10 + TextBetween(PageText, 'og:url" content="', '"')); // set movie page if (GetOption('ActorImage') = 1) and (ExtraPictureExists(index) = False) then DeleteExtra(index) else count := count - 1; end; end; 2: // Exchange actor(s) begin GetActorList(Value); // PickTree with actors index := GetExtraCount; for count := 0 to index - 1 do begin if (GetExtraField(count, eCategory) = 'Actors') and (IsExtraSelected(count) = TRUE) then // What if there are no more actors with pics? begin PickTreeTitle('Please choose an actor in exchange for - ' + GetExtraField(count, eTitle) + ':'); RemoveExtraPicture(count); // nedded when an actor with an image is replaced by an actor without an image if PickTreeExec(Value2) then GetActor('loadlate="' + Value2 + '</tr', count); end; end; end; end; end; // ***** Get actor list ***** procedure GetActorList(Value: String); var value2, value3: String; begin PickTreeClear; while POS('"/name/nm', Value) > 0 do begin if GetOption('ActorImage') = 1 then Value := TextAfter(Value, '<img alt="'); // find next actor with picture and set start string if Value = '' then exit; // otherwise last actor "with image" is additional empty dummy Value2 := TextBetween(Value, 'aria-label="', '"'); value3 := TextBefore(Value, 'width:100%">', ''); // 2 lines needed, because last actor has no such delimiter If Value3 = '' then Value3 := Value; HTMLDecode(Value2); PickTreeAdd(Value2, Value3); Value := TextAfter(Value, 'style="width:100%">'); end; end; // ***** Get actor ***** function GetActor(Value: String; index: Integer): String; var Value2: String; begin // Category SetExtraField(index, eCategory, 'Actors'); // Page Link Value2 := TextBetween(Value, '/name/', '/'); SetExtraField(index, eURL, Value2); // Picture Value2 := TextBetween(Value, '140w, ', ' 210w'); if Value2 <> '' then GetActorImage(Value2, GetExtraField(index, eURL), index); // Name Value2 := TextBetween(Value, 'aria-label="', '"'); HTMLDecode(Value2); SetExtraField(index, eTitle, Value2); // Character Value2 := TextBetween(Value, '<span', '</'); Value2 := TextAfter(Value2, '>'); if POS('(voice)', Value) > 0 then Value2 := Value2 + ' (voice)'; // for voice only actor HTMLDecode(Value2); SetExtraField(index, eDescription, Value2); end; // ***** Get actor image ***** procedure GetActorImage(Value2: String; Value3: String; index: Integer); var PageText: string; begin case GetOption('ImageLayout') of 0: Value2 := TextBefore(Value2, '._V1', ''); // Original Uncut photo 2: begin PageText := GetPage('https://www.imdb.com/name/' + Value3 + '/'); if PageText = '' Then SetStatic(ErrorMessage, GetStatic(ErrorMessage) + 'Picture Error at movie #' + GetField(fnumber) + ' - ' + GetField(fOriginalTitle) + #13#10); //**** ERROR Handling **** Value2 := TextBetween(PageText, '"ipc-image"', 'sizes='); Value2 := TextBetween(Value2, '140w, ',' 210w,'); end; end; if GetExtraPicture(index, Value2) = False Then SetStatic(ErrorMessage, GetStatic(ErrorMessage) + 'Picture Error at movie #' + GetField(fnumber) + ' - ' + GetField(fOriginalTitle) + #13#10); //**** ERROR Handling **** end; // ***** beginning of the program ***** begin // Check for current AMC version if CheckVersion(4,2,2) then begin RaiseConnectionErrors(False); // do not show error messages **** ERROR Handling **** if GetIteration = 0 then SetStatic(ErrorMessage, ''); //**** ERROR Handling **** MovieName := ''; if GetOption('BatchMode') = 2 then begin MovieName := GetField(fieldURL); if Pos('imdb.com', MovieName) = 0 then MovieName := ''; end; if MovieName = '' then MovieName := GetField(fieldOriginalTitle); if MovieName = '' then MovieName := GetField(fieldTranslatedTitle); if GetOption('BatchMode') = 0 then begin if not Input('IMDB Import', 'Enter the title or the IMDB URL of the movie:', MovieName) then Exit; end else Sleep(500); if MovieName <> '' then begin if Pos('imdb.com', MovieName) > 0 then AnalyzeResultsPage(MovieName) else if RegExprSetExec('tt[0-9]+', moviename) then AnalyzeResultsPage('https://www.imdb.com/title/' + MovieName) else begin MovieName := StringReplace(MovieName, #180, #39); // ´ -> ' if GetOption('ExactTitle') = 1 then begin MovieName := UrlEncode(UTF8Encode(StringReplace(MovieName, '&', #26 ))); // set dummy chars '%1A' for urlencode if pos('%1A', MovieName) > 0 then MovieName := StringReplace(MovieName, '%1A', '%26'); // change dummy chars back to '&' for final url AnalyzeResultsPage(ExactTitleSearchURL + MovieName); end else begin MovieName := UrlEncode(UTF8Encode(StringReplace(MovieName, '&', 'and' ))); AnalyzeResultsPage(PopularTitleSearchURL + MovieName); end end; end; if (GetIteration = GetIterationCount-1) AND (GetStatic(ErrorMessage) <> '') then ShowError(GetStatic(ErrorMessage)); //**** ERROR Handling **** end else ShowMessage('This script requires a newer version of Ant Movie Catalog (at least v4.2.2)'); end.