Det ville jo være smart - spørgsmålet er bare hvorfor de bruger pearl?
Men hvis jeg nu lige vender tilbage til kodningen - kan jeg tage det først program (m. source) som eks. og spørge hvorfor det ikke virker ?
unit IMDBImport;
interface
uses SysUtils, UrlMon, Classes;
const
TempFilename : ShortString = 'imdbtemp.###'#0;
type
TIMDBImport = Class
public
// Movie info fields
Title,
Year,
Director,
Rating,
Genre : ShortString;
// Will contain search results for more than one movie
SearchResults : TStringList;
// Will contain the URLs for search results
SearchResultsURLS : TStringList;
// After execute, will become true if found a movie, and false if found more than one result
FoundMovieInfo : Boolean;
Constructor Create;
Destructor Destroy; override;
Function Execute : Boolean;
Function GetMovieFromSearchResults(const Index : Integer) : Boolean;
private
// Will containt the downloaded file
FileStrings : TStringList;
// Will contain the current line used
LineIndex : Integer;
Procedure Init;
Function DownloadToFile(URL : ShortString) : Boolean;
Procedure GoToLine(Str : ShortString; const FromLine : Integer);
Procedure AnalyzeSearchResultsPage;
Procedure AnalyzeMoviePage;
end;
implementation
Constructor TIMDBImport.Create;
Begin
SearchResults := TStringList.Create;
FileStrings := TStringList.Create;
SearchResultsURLS := TStringList.Create;
end;
Destructor TIMDBImport.Destroy;
Begin
SearchResults.Free;
FileStrings.Free;
SearchResultsURLS.Free;
end;
// Initialize variables
Procedure TIMDBImport.Init;
Begin
SearchResults.Clear;
FileStrings.Clear;
SearchResultsURLS.Clear;
Genre := '';
Director := '';
Year := '';
Rating := '';
end;
// Skips lines in FileStrings until a line containing Str starting at FromLine
Procedure TIMDBImport.GoToLine(Str : ShortString; const FromLine : Integer);
Begin
Str := UpperCase(Str);
LineIndex := FromLine;
With FileStrings Do
Begin
While (LineIndex < Count) and (Pos(Str, UpperCase(Strings[LineIndex])) = 0) Do // Until no more lines or found what we're looking for
LineIndex := LineIndex + 1;
if LineIndex = Count then
LineIndex := -1; // Line not found. Reset the index
end; {With}
end;
// Downloads the page at URL to the file names TempFilename
Function TIMDBImport.DownloadToFile(URL : ShortString) : Boolean;
begin
URL := URL + #0;
try
Result := UrlDownloadToFile(nil, @URL[1], @TempFilename[1], 0, nil) = 0;
FileStrings.LoadFromFile(TempFilename); // Load the html file downloaded
except
Result := False;
FileStrings.Clear;
end;
end;
// Start the search and download. Returns true if all went ok
Function TIMDBImport.Execute : Boolean;
Begin
Result := False; // Assume it's bad
Init; // Initialize
if Title = '' then Exit; // No movie title to search for
if not DownloadToFile('
http://us.imdb.com/Tsearch?title=' + Title) then Exit; // try download the search page from IMDB
With FileStrings Do
Begin
GoToLine('<TITLE>', 0);
if Pos('>IMDB', UpperCase(Strings[LineIndex])) > 0 then // Found the line '<TITLE>IMDb name and title search</TITLE>'
AnalyzeSearchResultsPage // Process this page as a search results page
else
if Pos('<TITLE>THE', UpperCase(Strings[LineIndex])) > 0 then // Got the "no results" page
FoundMovieInfo := False
else
AnalyzeMoviePage; // Process this page as a move info page
end;
DeleteFile(TempFilename);
Result := True; // It probably didn't crush
end;
// Analyzes a search results page from IMDB and places the results in SearchResults and SearchResultsURLs
Procedure TIMDBImport.AnalyzeSearchResultsPage;
var
Temp : ShortString;
I : Byte;
Begin
FoundMovieInfo := False; // Found many results
GoToLine('"mov">Movies', 0); // Find where the big list starts
if LineIndex = -1 then Exit; // Not a search result page
With FileStrings Do
try
LineIndex := LineIndex + 1; // Skip this line
Repeat
Temp := Strings[LineIndex];
I := Pos('/TITLE', UpperCase(Temp));
System.Delete(Temp, 1, I - 1); // Delete all before the /Title?4539730
I := Pos('"', Temp);
SearchResultsURLS.Add('
http://us.imdb.com' + Copy(Temp, 1, I - 1)); // Copy the link to the movie match
System.Delete(Temp, 1, I + 1); // Delete the /Title?4539730 part and the " after it
I := Pos('<', Temp);
SearchResults.Add(Copy(Temp, 1, I - 1)); // Copy the movie match title
GoToLine('/title', LineIndex + 1); // Find the next movie in the list
Until (LineIndex = -1) or (Pos('</OL>', Strings[LineIndex]) > 0); // Until the end of the list or the file
Clear; // Clear the rest of the file
except
On EStringListError Do;
end; {try}
end;
// Downloads and process a movie from the SearchResults using Index.
// Returns true if download went ok
Function TIMDBImport.GetMovieFromSearchResults(const Index : Integer) : Boolean;
Begin
FoundMovieInfo := False; // Assume it doesn't go well
Result := False;
if Index > SearchResults.Count - 1 then Exit; // Out of range
if not DownloadToFile(SearchResultsURLs[Index]) then Exit; // Error downloading the movie info page
AnalyzeMoviePage; // Analyze the movie's info page
FoundMovieInfo := True; // It went ok
Result := True;
end;
// Processes the movie's info page and extracts the info
Procedure TIMDBImport.AnalyzeMoviePage;
var
P : Byte; // Temp for Pos
TempS : ShortString;
Begin
FoundMovieInfo := True; // Found a movie's info
With FileStrings Do
Begin
// Title and year
GoToLine('<TITLE>', 0); // The title looks like this: <title>100 Girls (2000)</title>
if LineIndex > -1 then
Begin
P := Pos('(', Strings[LineIndex]);
Title := Copy(Strings[LineIndex], 8, P - 2); // Copy the title without the space and the '('
Year := Copy(Strings[LineIndex], P + 1, 4); // Copy the year without the '('
end
else // No movie found
Begin
Init; // Reset all movie info
Exit;
end;
// Director
GoToLine('Directed by', LineIndex); // Find the director part. It's always after the title
if LineIndex > -1 then
Begin
P := Pos('">', Strings[LineIndex]); // <a href="/Name?Davis,%20Michael%20(II)">Michael Davis (II)</a><br>
Director := Copy(Strings[LineIndex], P + 2, Pos('</a>', Strings[LineIndex]) - P - 2); // Copy director's name
end;
// Genre
GoToLine('"ch">Genre:', 0); // Find the genre part
if LineIndex > -1 then
Begin
LineIndex := LineIndex + 1;
TempS := Strings[LineIndex];
While True Do
Begin
P := Pos('">', TempS); // <a href="/Sections/Genres/Comedy/">Comedy</a>
if (TempS[P + 2] = '(') or (P = 0) then Break; // No more genres. Found the (more)
if Genre <> '' then
Genre := Genre + ', '; // Add a comma if there's something already in there
System.Delete(TempS, 1, P + 1);
P := Pos('</a>', TempS);
Genre := Genre + Copy(TempS, 1, P - 1); // Copy current genre and add it
System.Delete(TempS, 1, P - 1);
end; {While}
end; {if}
//Rating
GoToLine('/10', 0); // Find rating
if LineIndex > -1 then
Begin
P := Pos('>', Strings[LineIndex]);
Rating := Copy(Strings[LineIndex], P + 1, Pos('/', Strings[LineIndex]) - P - 1);
(* If you want the rating as an integer:
try
// <b>6.0/10</b> (1,444 votes)
// Rating := Round(StrToFloat(Copy(Strings[LineIndex], P + 1, Pos('/', Strings[LineIndex]) - P - 1)));
except
on EConvertError Do
Rating := 0;
end;
*)
end; {if}
end; {With}
end;
end.