In an attempt to map out the network of Facebook (where people were nodes and friendships were edges), this script started with my Facebook friends, visited their profiles and got their friends, ad infinitum.
read moreon friendExtractionGivenan(id, type)
if type is equal to "indirect" then
tell application "Safari"
set doc to front document
set done_loading to false
do JavaScript "
window.location.assign('http://www.facebook.com/" & id & "?sk=friends&v=friends');
" in doc
delay 1
end tell
end if
if type is equal to "direct" then
tell application "Safari"
set doc to front document
set done_loading to false
do JavaScript "
window.location.assign('http://www.facebook.com/profile.php?id=" & id & "&sk=friends&v=friends');
" in doc
delay 1
end tell
end ife
tell application "Safari"
repeat while done_loading is not equal to true
set doc to front document
set done_loading to do JavaScript "
var done = false;
if (document.readyState=='complete'){
done=true;
}
done;
" in doc
delay 1
end repeat
end tell
tell application "Safari"
set doc to front document
set this_url to URL of doc
set done_scrolling to false
set filtered_URLs to {}
set completed_once to false
set erred_once to false
repeat while done_scrolling is not equal to true
try
set done_scrolling to do JavaScript "
var completed_once = " & completed_once & ";
if(completed_once!=true){
var done;
var number_of_trys =0;
}
function scrollToBottom(){
bottom = document.body.scrollHeight;
current = window.innerHeight+ document.body.scrollTop;
done = false;
if((bottom-current) >0){
window.scrollTo(0, bottom);
setTimeout (scrollToBottom, 1500 ); //If the loading exceeds this timeout, a try will be used.
}
else {
done = true;
}
};
if(completed_once!=true){
scrollToBottom();
}
if(done==true&&number_of_trys<10){//This number changes the number of allowed timeouts
done=false;
number_of_trys++;
setTimeout(scrollToBottom, 1000);
//This number sets the allotted timeout length.
//If the loading exceeds both the timeout above and this timeout, another try will be used immediately.
}
done;
" in doc
set completed_once to true
delay 1.0
on error
end try
end repeat
set URLs to false
repeat while URLs is equal to false
set URLs to do JavaScript "
URLArray = [];
allLinks = document.links;
for (i = 0; i < allLinks.length; i++) {
URLArray.push(allLinks[i].href);
}
URLArray;
" in doc
end repeat
return URLs
end tell
end friendExtractionGivenan
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on extractionOfIDsFrom(unfiltered_links)
set unfiltered to unfiltered_links
set filtered to {}
set direct_IDs to {}
set indirect_IDs to {}
set refined_IDs to {}
set returned_IDs to {}
repeat with x from 1 to count of items of unfiltered
set n to item x of unfiltered
if "=pb" is in n then
if n is not in filtered then set end of filtered to n
end if
end repeat
display dialog (filtered)
repeat with y from 1 to count of items of filtered
set profile to item y of filtered
if "profile.php?" is in profile then
set end of direct_IDs to text ((offset of "=" in profile) + 1) thru ((offset of "&" in profile) - 1) of profile
else
set end of indirect_IDs to text 25 thru ((offset of "?" in profile) - 1) of profile
end if
end repeat
return direct_IDs & indirect_IDs
end extractionOfIDsFrom
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on direct_indirect_ID_Checker(id)
try
id as integer
return "direct"
on error
return "indirect"
end try
end direct_indirect_ID_Checker
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on storeIDs(user_id, friends, database1)
tell application "Database Events"
tell database1
tell record "Completed Nodes"
make new field with properties {name:user_id, value:user_id}
end tell
tell record "IDs Awaiting Extraction"
if field user_id exists then
delete field user_id
end if
end tell
set node to make new record with properties {name:user_id}
tell node
repeat with x from 1 to count of items of friends
set friend_id to item x of friends
make new field with properties {name:"Friend " & x & "", value:friend_id}
end repeat
end tell
end tell
end tell
save database1
end storeIDs
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on existsInDatabaseChecker(user_id, database1)
tell application "Database Events"
if record user_id of database1 exists then
return true
else
return false
end if
end tell
end existsInDatabaseChecker
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on recursiveExtraction(database1)
set IDstobeextracted to {}
tell application "Database Events"
if (count of fields of record "IDs Awaiting Extraction" in database1) is equal to 1 then
repeat with y from 2 to count of fields of record "Completed Nodes" in database1
set userID to value of field y of record "Completed Nodes" in database1
repeat with x from 2 to count of fields of record userID in database1
set currentID to value of field x of record userID of database1
set end of IDstobeextracted to currentID
tell database1
tell record "IDs Awaiting Extraction"
make new field with properties {name:currentID, value:currentID}
end tell
end tell
end repeat
end repeat
else
repeat with y from 2 to count of fields of record "IDs Awaiting Extraction" in database1
set userID to value of field y of record "IDs Awaiting Extraction" in database1
set end of IDstobeextracted to userID
end repeat
end if
end tell
repeat with c from 1 to count of items in IDstobeextracted
set targetID to item c of IDstobeextracted
set dataAlreadyCollected to existsInDatabaseChecker(targetID, database1)
if dataAlreadyCollected is false then
set IDType to direct_indirect_ID_Checker(targetID)
set unfiltered_links to friendExtractionGivenan(targetID, IDType)
set returnedIDs to extractionOfIDsFrom(unfiltered_links)
storeIDs(targetID, returnedIDs, database1)
end if
end repeat
end recursiveExtraction
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on exportToPlist(database1)
tell application "System Events"
set parent_dictionary to make new property list item with properties {kind:record}
set the plistfile_path to ("Macintosh HD:Users:Puccio:Documents:My Documents:Scripts:Database:" & "Viewing.plist")
set plist to make new property list file with properties {contents:parent_dictionary, name:plistfile_path}
end tell
tell application "Database Events"
repeat with y from 1 to count of records in database1
set thefields to {}
set currentRecordName to name of record y of database1
repeat with x from 2 to count of fields of record currentRecordName in database1
set end of thefields to value of field x of record currentRecordName of database1
end repeat
tell application "System Events"
tell plist
set node to make new property list item at end with properties {kind:record, name:currentRecordName}
tell node
repeat with z from 1 to count of items of thefields
set fieldID to item z of thefields
make new property list item at end with properties {name:"Friend " & z & "", value:fieldID}
end repeat
end tell
end tell
end tell
end repeat
end tell
end exportToPlist
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
on interconnectnessOfFriendsAmongstThemselves(startingID, database1)
set connectionsOfNode to {}
set currentConnectionsNodes to {}
set totalMutualFriends to 0
tell application "Database Events"
repeat with x from 2 to count of fields of record startingID in database1
set currentID to value of field x of record startingID of database1
set end of connectionsOfNode to currentID
end repeat
end tell
set numberOfNodesFriends to count of items in connectionsOfNode
tell application "Database Events"
repeat with y from 1 to count of records in database1
set currentRecordName to name of record y of database1
if currentRecordName is not equal to "Completed Nodes" or "IDs Awaiting Extraction" or startingID then
repeat with x from 2 to count of fields of record currentRecordName in database1
set currentValue to value of field x of record currentRecordName of database1
if currentValue is in connectionsOfNode then
totalMutualFriends is equal to (totalMutualFriends + 1)
end if
end repeat
end if
end repeat
end tell
display dialog (totalMutualFriends / ((numberOfNodesFriends * numberOfNodesFriends) - numberOfNodesFriends))
end interconnectnessOfFriendsAmongstThemselves
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
set theOutputFolder to POSIX path of "Macintosh HD:Users:Puccio:Documents:My Documents:Scripts:Database:"
set databaselocation to POSIX path of "Macintosh HD:Users:Puccio:Documents:My Documents:Scripts:Database:Database.dbev"
tell application "Database Events"
set database1 to database databaselocation
end tell
set processCancelled to false
set IDgiven to false
repeat while IDgiven is not equal to true
set requestingStartingID to display dialog "What is the starting ID?" default answer "Monstermac77" with title "Facebook Data Extraction" buttons {"Indirect", "Direct", "More Options"} default button 1
set button_pressed to the button returned of the result
if the button_pressed is "Direct" then
set startingIDType to "Direct"
set IDgiven to true
else if the button_pressed is "Indirect" then
set startingIDType to "Indirect"
set IDgiven to true
else
display dialog "These are your options:
" with title "More Options" buttons {"Database Options", "Cancel Process", "Return to previous dialog"} default button 3
if the button returned of the result is "Database Options" then
display dialog "These are your options:
" with title "More Options" buttons {"Visualize Data", "Reset Database", "Return to original dialog"} default button 3
if the button returned of the result is "Reset Database" then
tell application "Database Events"
tell database1
delete every record
end tell
save database1
set database1 to make new database with properties {name:"Database", location:theOutputFolder}
tell database1
make new record with properties {name:"Completed Nodes"}
make new record with properties {name:"IDs Awaiting Extraction"}
end tell
save database1
end tell
else if the button returned of the result is "Visualize Data" then
exportToPlist(database1)
end if
else if the button returned of the result is "Cancel Process" then
set processCancelled to true
set IDgiven to true
end if
end if
end repeat
if processCancelled is false then
set startingID to text returned of requestingStartingID
set dataAlreadyCollected to existsInDatabaseChecker(startingID, database1)
if dataAlreadyCollected is false then
set unfiltered_links to friendExtractionGivenan(startingID, startingIDType)
set returnedIDs to extractionOfIDsFrom(unfiltered_links)
storeIDs(startingID, returnedIDs, database1)
display dialog "Would you like to continue to the next step?" buttons {"Yes", "No"} default button 1
if button returned of the result is "Yes" then
recursiveExtraction(database1)
end if
else
display dialog "The friends of this user have already been collected. Would you like to continue from where you left off?" buttons {"Yes", "No"} default button 1
if button returned of the result is "Yes" then
recursiveExtraction(database1)
end if
end if
end if