2010-12-15 13 views
1

Ich habe ein einfaches Screen Scraping Skript geschrieben und am Ende des Skripts versuche ich ein Array von Arrays in Vorbereitung für eine ActiveCord einfügen. Die Struktur I zu erreichen versuchen, ist wie folgt:Ruby Script zum Erstellen eines Array von Arrays

Array b hält eine Reihe von 10-Element-Arrays

b = [[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9],[0,1,2,3,4,5,6,7,8,9]] 

Zeit, wenn ich versuche Array auszudrucken b das Array leer ist. Ich bin immer noch relativ neu in Sachen Ruby und Programmierung und würde mich über jede Rückmeldung freuen, wie man Werte in Array b erhält und das Gesamt-Skript verbessert. Skript folgt:

require "rubygems" 
require "celerity" 
t = 0 
r = 0 
c = 0 
a = Array.new(10) 
b = Array.new 

    #initialize Browser 
    browser = Celerity::IE.new 
    #goto Login Page 
    browser.goto('http://www1.drf.com/drfLogin.do?type=membership') 
    #input UserId and Password 
    browser.text_field(:name, 'p_full_name').value = 'username' 
    browser.text_field(:name, 'p_password').value = 'password' 
    browser.button(:index, 2).click 
    #goto DRF Frontpage 
    browser.goto('http://www.drf.com/frontpage') 
    #goto DRF Entries 
    browser.goto('http://www1.drf.com/static/indexMenus/eindex.html') 
    #click the link to access the entries 
    browser.link(:text, '09').click 

    browser.tables.each do |table| 
    t = t + 1 
     browser.table(:index, t).rows.each do |row| 
     r = r + 1 
      browser.table(:index, t).row(:index, r).cells.each do |cell| 
      a << cell.text 
      end 
      b << a 
      a.clear   
     end 
     r = 0 
    end 
    puts b 
    browser.close 
+1

Beachten Sie, dass Sie, anstatt den Großteil des Skripts zu veröffentlichen, die Zeilen, die sich mit 'browser' befassen, leicht ersetzen können, wodurch ein kleineres, eigenständigeres Beispiel entsteht (http://sscce.org/). Das Beispiel ist ohne Benutzernamen und Kennwort nicht ausführbar, und mindestens die Hälfte des Codes ist zumindest für diese Frage irrelevant. – outis

Antwort

2

ein Minderjähriger eine Ruby-artig Dieses Umschreiben Ihrer Hauptschleife.

Ich habe die Array-Initialisierungen direkt darüber verschoben, wo sie benötigt werden. Das ist natürlich eine Wahl für Programmierer.

Anstatt zwei Zählervariablen oben zu erstellen, wechselte ich zu each_with_index, die eine Indexvariable beginnend bei 0 hinzufügt. Um Ihre 1-Offsets zu bekommen, füge ich 1 hinzu.

Sie sind keine großen Änderungen, aber sie addieren sich zu einer kohärenteren App.

Zurück zum ursprünglichen code: Ein Problem, das ich sehe, ist, dass Sie Ihre a Array außerhalb der Schleifen dann wieder verwenden, wenn Sie b zuweisen. Das bedeutet, dass jedes Mal dasselbe Array verwendet, aber gelöscht und Werte gespeichert werden. Dies führt dazu, dass die vorherigen Array-Werte überschrieben werden, was jedoch zu doppelten Arrays in b führt.

require 'pp' 

a = [] 
b = [] 

puts a.object_id 

a[0] = 1 
b << a 
a.clear 

a[0] = 2 
b << a 

puts 
pp b 
b.each { |ary| puts ary.object_id } 
# >> 2151839900 
# >> 
# >> [[2], [2]] 
# >> 2151839900 
# >> 2151839900 

Beachten Sie, dass die a Array immer wieder verwendet wird.

Wenn ich a zu einem zweiten Array ändern gibt es zwei Werte für b und a zwei separate Objekte:

require 'pp' 

a = [] 
b = [] 

puts a.object_id 

a[0] = 1 
b << a 
a = [] 

a[0] = 2 
b << a 

puts 
pp b 
b.each { |ary| puts ary.object_id } 
# >> 2151839920 
# >> 
# >> [[1], [2]] 
# >> 2151839920 
# >> 2151839780 

Hoffentlich werden Sie helfen, das Problem in Zukunft zu vermeiden.

+0

Ja, das hilft ziemlich viel. Danke .... – Mutuelinvestor

+0

Kein Problem. Umgang mit Zeigern AKA-Verweise auf Objekte oder Strukturen, ist eine der ersten Hürden, die wir beim Programmieren lösen müssen. Sie werden Sinn machen, wenn Sie sie erst einmal geknackt haben und wirklich mächtig sind, aber Sie werden in der Zwischenzeit etwas davon bekommen. Rubin isoliert uns von ihnen; Ich glaube nicht, dass ich ohne sie in Perl oder C programmieren könnte. :-) –

+0

@Mutuelinvestor, hast du dein Array korrekt ausgefüllt? Wenn du deine ursprüngliche Frage nicht mit deinem aktuellen Stand der Dinge aktualisierst, werden wir weiter daran arbeiten. –

2

Ihr Problem ist es am Ende:

b << a # push a *reference to* a onto b 
a.clear # clear a; the reference in b now points to an empty array! 

Wenn Sie den Verweis entfernen, um a.clear und diese Schleife beginnen mit:

browser.tables.each do |table| 
    t = t + 1 
    a = [] 

... Sie werden golden sein (zumindest so weit wie Ihr Array-Gebäude geht)

+0

Bill danke für die Antwort. Ich habe das versucht und ich bekomme jetzt Daten im Array. aber anstatt 1 Array mit 10 Elementen zu erhalten (d. h. die Datenzeile) bekomme ich 10 Arrays mit 10 Elementen. Deshalb habe ich das a = [] runter unter den r = r + 1 bewegt, weil ich dachte, dies würde mir geben, wonach ich suche, und jetzt bin ich wieder dabei, keine Daten im Array zu bekommen. – Mutuelinvestor

1

Ich kann nicht aus Ihrer Frage sagen, ob Sie mehrere Tabl haben es oder nicht. Vielleicht nur einer? In diesem Fall:

b = browser.tables.first.rows.map {|row| row.cells.map(&:text)} 

Wenn Sie mehrere Tabellen haben, und wirklich wollen, ein Array (Tabellen) von Arrays (Zeilen) von Arrays (Zellen), wäre die

b = browser.tables.map {|t| t.rows.map {|row| row.cells.map(&:text)}} 

Und wenn die Tische sein alle haben die gleiche Struktur und Sie einfach alle Zeilen wollen, als ob sie in einem großen Tisch waren, können Sie tun:

b = browser.tables.map {|t| t.rows.map {|row| row.cells.map(&:text)}}.flatten(1) 
+0

Glen Danke für die Antwort. Ich habe tatsächlich mehrere Tabellen. Ich bin mit dem Befehl map nicht vertraut. Wenn ich ein wenig recherchiert habe, feuere ich Ihren Vorschlag ab. Wie ändert sich Ihre Antwort im Szenario mit mehreren Tabellen? – Mutuelinvestor

+0

Haben alle Tabellen dieselbe Zeilenstruktur? Oder wollen Sie wirklich ein Array (Tabellen) von Arrays (Zeilen) von Arrays (Zellen)? –

+0

Die Geschichten haben die gleiche Zeilen- und Zellenstruktur. Ich füge Daten in eine Datenbank unter Verwendung einer Masseneinfügung ein Gem: http://rorstuff.blogspot.com/2010/05/activerecord-bulk-insertion-of-data-in.html Meine Daten haben normalerweise 8 bis 10 Tabellen mit jedem Tisch irgendwo zwischen 5 und 12 Zeilen. Jede Reihe hat 10 Zellen (td). Dies ist der Fall, wenn ich richtigerweise annehme, dass Ihre zweite Option mit dem übereinstimmt, was ich erreichen möchte. – Mutuelinvestor

Verwandte Themen