Thread Eure Einschätzung: lokale HTML parsen und Werte in Remote-MySQL einfügen ? (5 answers)
Opened by mzurhorst at 2012-03-28 12:55

mzurhorst
 2012-04-06 17:04
#157297 #157297
User since
2012-03-28
9 Artikel
BenutzerIn
[default_avatar]
Hallo zusammen!

Mühsam ernährt ich das Eichhörnchen. Aber irgendwie kommt es wohl über den Winter *gg*

Ich mache Fortschritte. Allerdings frage ich mich gerade, ob ich mich total ungeschickt verhalte, und das nicht effizienter gemacht werden könnte.

Gebt mir doch mal bitte Feedback, falls ich zu kompliziert vorgehe.
Ich tue mir insbesondere schwer, in diesem CPAN Verzeichnis die richtigen Module zu finden. Entweder suche ich falsch und finde nichts, oder ich finde 20 Module die alle das gleiche machen (aus Sicht eines Laien zumindest)


Mein Vorgehen hat sich doch etwas geändert:
1) ich kann mich nun doch mit der Remote-Datenbank verbinden. Mein Provider hat den Zugang eingerichtet.
2) für's erste werde ich nicht (mühsam) erforschen, welche Unterverzeichnisse sich veränderten oder nicht. (mit Inotify oder so).
3) stattdessen werde ich jedesmal komplett durch alle Verzeichnisse laufen.
4) dann lese ich die Sachen ein und schreibe sie in ein SQLite Datenbank hier lokal.
5) Wenn ich diese Zeile bereits habe, dann prüfe ich lediglich ob sich der Status des Caches geändert hat
6) wenn ja, dann ändere ich den Status und merke mir das in einer Zusatzspalte mit dem Kommentar "UPDATE". Sonst lass' ich diese Zeile fallen.
7) Wenn ich die Zeile noch nicht habe, dann schreibe ich die ganze Zeile und merke mir dies als "NEW"
8) Anschließend kopiere ich die Zeilen mit NEW und UPDATE von der SQLite-Datei auf den Remote-Server


Noch nicht gelöst habe ich:
a) Ich muss die Zeilen noch sortieren. Da ist eine Datumsstring in der notes.txt Datei drin. Das Sortieren müsste dann aber gesehen, bevor ich in die lokale Datenbank schreibe, nur habe ich da keine Idee.
b) ich bekomme das rekursive Öffnen der Verzeichnisse noch nicht hin.



Bisher ist alles nur rudimentär, aber es funktioniert jetzt:
1) ich kann den Pfad zum Arbeitsverzeichnis auslesen aus der Config-Datei von Geolog.pl
2) ich kann dann zu dem Verzeichnis wechseln
3) ich kann mich mit den Datenbanken verbinden


Und hier mal mein Skript.
more (26.0kb):

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/usr/bin/perl
#
use 5.006;
use utf8;
use strict;
use warnings;
use DBI;
use DBD::mysql;
use Cwd;
#
#  ********* BEGIN Settings *********
#  1) Remote MySQL Database
#     a) Remote Database
#       my $remote_dsn = 'dbi:mysql:dbname=xxxxxxx;host=xxxxxxx';
#       my $remote_user = 'xxxxxxx';
#       my $remote_password = 'xxxxxxx';
#
#     b) Local Test-Database 
      my $remote_dsn = 'dbi:mysql:dbname=xxxxxxx;host=xxxxxxx';
      my $remote_user = 'xxxxxxx';
      my $remote_password = 'xxxxxxx';
#
#  2) Local SQLite Database (hosts all geocaches found)
      my $sqlite_file = "/home/marcus/.gcfounds2mysql/foundcaches.db";
      my $local_dsn = 'dbi:SQLite:dbname=$sqlite_file","",""';
#
#  3) Geolog.pl option file and search term for the working directory
      my $geolog_optionfile = "/home/marcus/.geolog/profile.txt";
      my $searchstring1 = 'directory: ';
#
#  4) Relative path from working directory to the found geocaches
#     Caution: leading and trailing slashes required!
      my $workdir = "/found/";
#
#  ********* END Settings *********
#
#
#
#  ********* BEGIN "Read geolog.pl working dir from its option file" *********
#
# open file; OPTIONFILE is the file handle
open (OPTIONFILE,$geolog_optionfile) or die "Error: profile.txt file cannot be opened!\n$!";
# walk line by line through the file
while (<OPTIONFILE>){            
        my $line1 = $_; # read the current line
        chomp $line1;   # remove the trailing character
        # Test: if line starts with the search string ...
        if ($line1=~/$searchstring1/) {
                    # split line into separate strings, separated by blanks
                    my @line2=split(/: /,$line1);
                    # the last value of the array is our path
                    # we add this in front of the $workdir
                    $workdir=$line2[-1].$workdir;
                    print "1: found the working directory in file $geolog_optionfile: \n$workdir\n";
                    last;
                    }
        }
# close file again
close(OPTIONFILE);
#
#  ********* END *********
#
#
# STEP 1  RECURSIVELY WALK THROUGH ALL SUB DIRECTORIES:
# STEP 1.1   change to the working directory
#
# change the directory
chdir($workdir) or die "Error: Cannot change to working directory!\n   $!";
print "2: changed to the working directory\n$workdir\n";
#
#
# STEP 1.2   open directory and read all sub directories
opendir (DIR,'.') or die "Error: Working directory cannot be opened!\n$!"; 
while(my $subdir = readdir (DIR)) {           
            print "$subdir\n";
            print "$workdir\n";
            my $subdir2 = $workdir;
            print "4: TEST\n";
            print "5: Subdir: $subdir2\n";

            $subdir2.=$subdir."\/";  # append current directory + trailing slash
            print "\n\n6: Directory: ",$subdir2,"\n";
            print "7: $subdir2\n";
            opendir (SUBDIR,'$subdir2') or die $!;
            while(my $cachefiles = readdir (SUBDIR))
                      {
                        print $cachefiles,"\n";
                      }
            # closes the sub directory after each inner loop
            closedir (SUBDIR);
          }
# closes the workdir at end of the main loop
closedir (DIR);


# --> DEBUG:  close early
exit;



# TODO 4 DATABASE LAYOUTS
# TODO 4.1  SQLite table layout (temporary)
# TODO *  Finalize Layout of local SQLite database
# Current Layout:  (temporary, testing only)
#       TABLE `main` 
#              `gcnumber` INTEGER PRIMARY KEY 
#              `gcid`     TEXT 
#              `gcstatus` TEXT 
#              `dbstatus` TEXT
#

# STEP 5 CONNECT TO LOCAL SQLite DATABASE
# # Establish connection to local SQLite database
# my $local_dbh = DBI->connect($local_dsn, { RaiseError => 1, AutoCommit => 1 }) 
              # #  DBI->connect failed:
              # or die('DBI->connect to SQLite File failed:' . DBI->errstr());
# 
# my $rv = $local_dbh->last_insert_id(undef, undef, undef, undef);
# print "last_insert_id: ", $rv, "\n";
# 
# # Disconnect from the SQLite file                    
# $local_dbh->disconnect;
#

# --> DEBUG:  close early
exit;


#
# 
# STEP 10  CONNECT TO REMOTE DATABASE
#
# Establish connection to remote database.
# Connection will be held during all transactions.
print "Establish connection to remote database...\n";

my $remote_dbh = DBI->connect($remote_dsn, $remote_user, $remote_password,
                    { RaiseError => 1, AutoCommit => 1 }) 
              #  DBI->connect fehlgeschlagen:
              or die('DBI->connect fehlgeschlagen:' . DBI->errstr());






# Danach für jeden Eintrag des Arrays einen Statement-Handle aufmachen
# in der Schleife jeweils prepare & execute & finish


## ERSTE TESTS
my $db_gcnumber = '138';

# $sth is statement handler
my $sth = $remote_dbh->prepare('SELECT * FROM jml_geocaches WHERE gcnumber >= ?') 
               or die('Kann keine Verbindung zur Datenbank aufbauen. Fehler: ' . DBI->errstr());

my $rv = $sth->execute($db_gcnumber) 
               or die('Kann Statement nicht ausführen: ' . DBI->errstr());


print "rv = $rv\n";   # returns the number of search results


                    
# Finalize the statement handler.
$sth->finish();
               
# Disconnect from the remote database                    
$remote_dbh->disconnect;


# Job done; 
exit;




Ich würde gerne ein paar Abkürzungen nehmen.
Allerdings weiß ich nicht wie:

1) ich kenne den genauen Namen meiner "Schlüssel" in den Dateien.
Kann ich das einlesen der Dateien auf 1-2 Zeilen reduzieren mit eines geeigneten Moduls ?

2) außerdem weiß ich, dass sämtliche Verzeichnisse dem Muster xxxxxxxxx_GCyyyyy entsprechen. Kann ich davon profitieren, wenn ich auf ein paarmal Fehlerabfangen verzichte ?


Viele Grüße und schöne Feiertage!
Marcus

modedit Editiert von pq: more-tags um code hinzugefügt
Last edited: 2012-04-06 17:28:52 +0200 (CEST)

View full thread Eure Einschätzung: lokale HTML parsen und Werte in Remote-MySQL einfügen ?