Added _print()

pull/5/head
Lasse Edfast 5 years ago
parent 2569dfca7f
commit 35639cfe41
  1. 96
      facebook/__main__.py
  2. 4
      facebook/arangodb.py
  3. 142
      facebook/scrapers.py

@ -3,21 +3,37 @@ import traceback
from getopt import GetoptError, getopt from getopt import GetoptError, getopt
from sys import argv, exit from sys import argv, exit
from time import sleep from time import sleep
from subprocess import check_output
from re import split
from socket import gethostname
import arangodb from arangodb import db, write_report, backup, report_blocked, get_profile, remove_profile, checked_members, friends_of_user
from arangodb import db, write_report, backup, report_blocked
from classes import Profile, User from classes import Profile, User
from helpers import sleep_, write_error from helpers import sleep_, write_error, _print
from scrapers import profile_picture_reactions from scrapers import profile_picture_reactions
# import werkzeug
# werkzeug.cached_property = werkzeug.utils.cached_property
# from arango import ArangoClient
def finish():
""" Avslutar: skriver rapport och gör profilerna oanvända """
for profile in profiles:
profile.unused()
write_report(users, list(all_pictures.difference(all_pictures_start)))
exit()
if __name__ == "__main__": if __name__ == "__main__":
print() print()
if gethostname() not in ['macbook.local']: # Lägg till för studiodatorn
# Hämta namn för containern där skriptet körs
try:
containers = check_output(['docker', 'container', 'ls']).decode()
container = split('\W\W+', containers.split('\n')[1])[-1]
except FileNotFoundError:
pass
else:
container_name = 'macbook'
# Argument och alternativ # Argument och alternativ
argv = argv[1:] argv = argv[1:]
try: try:
@ -30,16 +46,21 @@ if __name__ == "__main__":
mode_nr = 1.7 mode_nr = 1.7
elif mode == 'few': elif mode == 'few':
mode_nr = 1.4 mode_nr = 1.4
elif mode == 'force':
mode_nr = 1
else: else:
mode = 'all' mode = 'all'
mode_nr = 1 mode_nr = 1
for o, a in opts: for o, a in opts:
if o in ["-u", "--user"]: if o in ["-u", "--user"]:
try:
users = [ users = [
User(str(i).strip(), mode) User(str(i).strip(), mode)
for i in [(str(i).strip()) for i in a.split(",")] for i in [(str(i).strip()) for i in a.split(",")]
] ]
except StopIteration:
raise Exception
if o in ["-o", "--other"]: if o in ["-o", "--other"]:
url_other_picture = a url_other_picture = a
if o in ['-b', '--backup']: if o in ['-b', '--backup']:
@ -72,14 +93,20 @@ if __name__ == "__main__":
print("-", user.username) print("-", user.username)
print() print()
if 'container' not in globals():
usernames = [user.username for user in users]
if len(usernames) == 1:
container = usernames[0]
else:
container = '-'.join(usernames)
# Skapa tre olika profiler att besöka Facebook med # Skapa tre olika profiler att besöka Facebook med
profiles = [] profiles = []
for i in range(0, 3): for i in range(0, 3):
doc = arangodb.get_profile() doc = get_profile()
profile = Profile(doc) profile = Profile(doc, container)
profile.browser.open("https://api.ipify.org") profile.browser.open("https://api.ipify.org")
print( print(f"Profil {profile.name} använder IP-adress {profile.viewing().text}."
f"Profil {profile.name} använder IP-adress {profile.viewing().text}."
) )
if profile.logged_in == False: if profile.logged_in == False:
profile.accept_cookies() profile.accept_cookies()
@ -92,7 +119,7 @@ if __name__ == "__main__":
profile_nr = 1 profile_nr = 1
profile = profiles[profile_nr] profile = profiles[profile_nr]
print("Börjar med profilen", profile.name) _print(profile.container, user.username, f"Börjar med profilen {profile.name}")
# Gå igenom de användare som efterfrågats # Gå igenom de användare som efterfrågats
try: try:
@ -101,26 +128,28 @@ if __name__ == "__main__":
# Set för kollade bilder och kollade medlemmar # Set för kollade bilder och kollade medlemmar
all_pictures = set([doc["_key"] for doc in db.collection("pictures").all()]) all_pictures = set([doc["_key"] for doc in db.collection("pictures").all()])
all_pictures_start = all_pictures.copy() all_pictures_start = all_pictures.copy()
members_checked = arangodb.checked_members() members_checked = checked_members()
profile.container = user.username
if user.username not in members_checked:# Hämta reaktioner för den första användaren LÄGG TILL NOT IN MEMBERS_CHECKED # Hämta reaktioner för den första användaren
if any([user.username not in members_checked, mode == 'force']):
try: try:
profile_picture_reactions(profile, user, all_pictures, first_user=True, mode=mode) profile_picture_reactions(profile, user, all_pictures, first_user=True, mode=mode)
except: except:
print(traceback.format_exc()) _print(profile.container, user.username, traceback.format_exc())
if len(users) == 1: if len(users) == 1:
for profile in profiles: for profile in profiles:
profile.unused() profile.unused()
friends = arangodb.friends_of_user(user.username) friends = friends_of_user(user.username)
friends_unchecked = list(set(friends) - set(members_checked)) friends_unchecked = list(set(friends) - set(members_checked))
# Här följer cookien med så att vi fortfarnade är inloggade
print("\nKlar med", user.username, "\n")
print("Vänner som reagerat:", len(friends)) _print(profile.container, user.username, f"\nKlar med, {user.username}\n")
print("Vänner att kolla:") _print(profile.container, user.username, f"Vänner som reagerat: {len(friends)}")
_print(profile.container, user.username, "\nVänner att kolla:")
for friend in friends_unchecked: for friend in friends_unchecked:
print(friend) print(friend)
_print(profile.container, user.username, ', '.join([friend for friend in friends_unchecked]), silent=True)
print() print()
# Hämta reaktioner för users vänner (som reagerat) # Hämta reaktioner för users vänner (som reagerat)
@ -139,25 +168,26 @@ if __name__ == "__main__":
4, 4,
e=e, e=e,
user=user.username, user=user.username,
profile=profile.container,
traceback=traceback.format_exc(), traceback=traceback.format_exc(),
soup=profile.viewing(), soup=profile.viewing(),
) )
print("\nFel: ", str(user.username), "\n") _print(profile.container, user.username, f"\nFel: {str(user.username)}\n")
sleep_(15) sleep_(15)
if profile.blocked == False: if profile.blocked == False:
print("Klar med", user.username, "\n") _print(profile.container, user.username, f"Klar med {user.username} \n")
# Rotera fb-profiler # Rotera fb-profiler
if count_friends > 5 * mode_nr: if count_friends > 5 * mode_nr:
if random.randrange(0, 2, 1) == 1: if random.randrange(0, 2, 1) == 1:
profile_nr += 1 profile_nr += 1
count_friends = 0 count_friends = 0
print("Växlar till", profiles[profile_nr].name) _print(profile.container, user.username, f"Växlar till {profiles[profile_nr].name}")
elif count_friends > 9 * mode_nr: elif count_friends > 9 * mode_nr:
profile_nr += 1 profile_nr += 1
count_friends = 0 count_friends = 0
print("Växlar till", profiles[profile_nr].name) _print(profile.container, user.username, f"Växlar till {profiles[profile_nr].name}")
if profile_nr > len(profiles) - 1: if profile_nr > len(profiles) - 1:
profile_nr = 0 profile_nr = 0
@ -165,31 +195,27 @@ if __name__ == "__main__":
elif profile.blocked == True: elif profile.blocked == True:
# Ta bort profilen ur databasen # Ta bort profilen ur databasen
report_blocked(profile, users) report_blocked(profile, users)
arangodb.remove_profile(profile.doc) remove_profile(profile.doc)
# Ta bort från listan på fb-profiler som används # Ta bort från listan på fb-profiler som används
profiles.remove(profile) profiles.remove(profile)
# Försök lägga till en ny fb-profil (om det finns en skapad och ledig i databasen) # Försök lägga till en ny fb-profil (om det finns en skapad och ledig i databasen)
try: try:
profiles[profile_nr] = Profile(new=True) doc = get_profile()
print("Laddat ny profil:", profiles[profile_nr].name) profiles[profile_nr] = Profile(doc, container)
_print(profile.container, user.username, f"Laddat ny profil: {profiles[profile_nr].name}")
sleep(3) sleep(3)
except e: except e:
print("Det behövs nya profiler...") _print(profile.container, user.username, "Det behövs nya profiler...")
if len(profiles) == 0: if len(profiles) == 0:
break break
for s in range(0, 1600 / len(profiles)): for s in range(0, 1600 / len(profiles)):
print(f"Sover {600-s} sekunder till... ", end="\r") print(user, f"Sover {600-s} sekunder till... ", end="\r")
profile_nr += 1 profile_nr += 1
print(f"Försöker med {profiles[profile_nr].name}.") _print(profile.container, user.username, f"Försöker med {profiles[profile_nr].name}.")
profile = profiles[profile_nr] profile = profiles[profile_nr]
except: except:
pass finish()
# Gör profilerna oanvända
for profile in profiles:
profile.unused()
write_report(users, list(all_pictures.difference(all_pictures_start)))
exit()

@ -32,7 +32,7 @@ except FileNotFoundError:
db = ArangoClient(hosts=host_arango).db(db_arango, username=user_arango, password=pwd) db = ArangoClient(hosts=host_arango).db(db_arango, username=user_arango, password=pwd)
from helpers import now from helpers import now, _print
def checked_members(): def checked_members():
@ -106,7 +106,7 @@ def friends_of_user(user):
def remove_profile(profile): def remove_profile(profile):
db.collection("profiles").delete(profile['_key'], silent=True, ignore_missing=True) db.collection("profiles").delete(profile['_key'], silent=True, ignore_missing=True)
_print(profile.name, f'{profile.name} blockerad och borttagen {now()}.' _print(profile.container, f'{profile.name} blockerad och borttagen {now()}.'
) )
# TODO #2 Bättre funktion för backup av databasen # TODO #2 Bättre funktion för backup av databasen

@ -4,10 +4,12 @@ import traceback
from arangodb import db from arangodb import db
from classes import Friend, Picture, Reaction from classes import Friend, Picture, Reaction
from config import * from config import *
from helpers import sleep_, update_cookie, write_error from helpers import sleep_, update_cookie, write_error, _print
def profile_picture_reactions(profile, user, all_pictures, first_user=False, mode = 'all'): def profile_picture_reactions(
profile, user, all_pictures, first_user=False, mode="all"
):
# Fixa url:er osv # Fixa url:er osv
if user.username.isnumeric(): if user.username.isnumeric():
@ -27,11 +29,11 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
"""You can't use Facebook because your account, or activity on it, doesn't follow our Community Standards.""" """You can't use Facebook because your account, or activity on it, doesn't follow our Community Standards."""
in profile.viewing().text in profile.viewing().text
): ):
print("{} blocked\n".format(profile.name).upper()) _print(profile.container, user.username, f"{profile.name} blocked\n".upper())
profile.blocked = True profile.blocked = True
return None return "blocked"
elif 'accept all' in profile.viewing().text.lower(): elif "accept all" in profile.viewing().text.lower():
profile.accept_cookies() profile.accept_cookies()
profile.browser.open(user.url_photos) profile.browser.open(user.url_photos)
@ -47,18 +49,15 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
6, 6,
e=e, e=e,
traceback=traceback.format_exc(), traceback=traceback.format_exc(),
profile=profile.container,
soup=profile.viewing(), soup=profile.viewing(),
user=user.username, user=user,
url=user.url_photos, url=user.url_photos,
) )
if first_user == True: if first_user == True:
print(profile.viewing().prettify()) _print(profile.container, user.username, profile.viewing().prettify())
exit() exit()
print( _print(profile.container, user.username, f"Hämtar reaktioner på profilbilder för {user.name} ({user.username})")
"Hämtar reaktioner på profilbilder för {name} ({user})".format(
name=user.name, user=user.username
)
)
# Hitta länk till olika saker hos användarem, inkl facebook-id # Hitta länk till olika saker hos användarem, inkl facebook-id
@ -85,26 +84,33 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
# Testa ta bort mellanrum och små bokstäver # Testa ta bort mellanrum och små bokstäver
if not hasattr(user, "url_album"): if not hasattr(user, "url_album"):
for a in profile.viewing().find_all("a", href=True): for a in profile.viewing().find_all("a", href=True):
if "profilepictures" in a.text.lower().replace(' ', ''): if "profilepictures" in a.text.lower().replace(" ", ""):
user.url_album = url_bas + a["href"] user.url_album = url_bas + a["href"]
user.add_to_db() user.add_to_db()
# Gå till profilbilden (den första som kommer upp när man går till profilen) # Gå till profilbilden (den första som kommer upp när man går till profilen)
if not hasattr(user, "url_album"): # Om profilen inte har profilalbum if not hasattr(user, "url_album"): # Om profilen inte har profilalbum
write_error(9, soup=profile.viewing(), user=user.username) write_error(9, soup=profile.viewing(), user=user, profile=profile.container)
if user.url_other_picture != '': if user.url_other_picture != "":
# Använd eventuell extrabild och ta bort den från användaren # Använd eventuell extrabild och ta bort den från användaren
url_pics = [user.url_other_picture] url_pics = [user.url_other_picture]
user.url_other_picture = '' user.url_other_picture = ""
else: else:
# Spara ner profilen till databasen och avsluta sökningen på användaren # Spara ner profilen till databasen och avsluta sökningen på användaren
user.url_album = False user.url_album = False
if first_user == False: if first_user == False:
user.checked() user.checked()
user.add_to_db() user.add_to_db()
print('Hittar inget album för profilbilder.') _print(profile.container, user.username, "Hittar inget album för profilbilder.")
write_error(7, soup=profile.viewing(), user=user.username, url=user.url_album, url_name='user.url_album') write_error(#fel7
7,
soup=profile.viewing(),
profile=profile.container,
user=user,
url=user.url_album,
url_name="user.url_album",
)
return None return None
# ATT GÖRA Här kan andra bilder väljas istället # ATT GÖRA Här kan andra bilder väljas istället
@ -117,10 +123,10 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
for i in pics.find_all("a"): for i in pics.find_all("a"):
a = i["href"] a = i["href"]
url_pics.append(a[: a.find("&id")]) url_pics.append(a[: a.find("&id")])
if user.url_other_picture != '': if user.url_other_picture != "":
# Lägg till eventuell extrabild och ta bort den från användaren # Lägg till eventuell extrabild och ta bort den från användaren
url_pics.append(user.url_other_picture) url_pics.append(user.url_other_picture)
user.url_other_picture = '' user.url_other_picture = ""
try: try:
user.profile_pictures = len(url_pics) user.profile_pictures = len(url_pics)
except: except:
@ -133,21 +139,39 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
# Välj vilja bilder som ska kollas. # Välj vilja bilder som ska kollas.
if first_user == False: if first_user == False:
if mode == 'single': if mode == "single":
url_pics = url_pics[:1] url_pics = url_pics[:1]
elif mode == 'few' and len(url_pics) > 1: elif mode == "few" and len(url_pics) > 1:
url_pics = url_pics[:1] + url_pics[-1:] url_pics = url_pics[:1] + url_pics[-1:]
# Gå igenom valda bilder. # Gå igenom valda bilder.
for pic in url_pics: for pic in url_pics:
# Skriv ut vilken bild som behandlas. # Skriv ut vilken bild som behandlas.
print(f"Bild {url_pics.index(pic) + 1} av {user.profile_pictures}", end="\r",) _print(profile.container, user.username,
f"Bild {url_pics.index(pic) + 1} av {user.profile_pictures}",
end="\r",
)
check_picture(url_bas + pic, user, profile)
# Välj vilja bilder som ska kollas.
if first_user == False:
if mode == "single" and user.reactions > 30:
break
elif all([mode == "few", user.reactions > 50, pic != url_pics[-1]]):
# Kolla den sista bilder
check_picture(url_bas + url_pics[-1], user, profile)
break
user.checked()
def check_picture(url_picture, user, profile):
""" Hämtar reaktioner för en bildprint """
picture = Picture(user.username) picture = Picture(user.username)
picture.url = url_bas + pic picture.url = url_picture
picture.id = str(picture.url[picture.url.find("fbid=") + 5 :]) picture.id = str(picture.url[picture.url.find("fbid=") + 5 :])
try: try:
picture.id = str(re.search('\d+', picture.id).group()) picture.id = str(re.search("\d+", picture.id).group())
except: except:
pass pass
# if picture.id in all_pictures: # if picture.id in all_pictures:
@ -160,8 +184,9 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
write_error( write_error(
3, 3,
e=e, e=e,
profile=profile.container,
soup=profile.viewing(), soup=profile.viewing(),
user=user.username, user=user,
url=picture.url, url=picture.url,
url_name="url_pic", url_name="url_pic",
traceback=traceback.format_exc(), traceback=traceback.format_exc(),
@ -173,11 +198,20 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
try: try:
picture.date = profile.viewing().find("abbr").text picture.date = profile.viewing().find("abbr").text
except Exception as e: # Fel8 except Exception as e: # Fel8
write_error(8, e=e, soup=profile.viewing(), url=pic, url_name='picture url', user=user.name, traceback=traceback.format_exc()) write_error(
8,
e=e,
soup=profile.viewing(),
profile=profile.container,
url=picture.url,
url_name="picture url",
user=user,
traceback=traceback.format_exc(),
)
# TODO #3 lägg till fler bilder som kan gås igenom om det är få profilbilder. # TODO #3 lägg till fler bilder som kan gås igenom om det är få profilbilder.
# Hämta länkar för bilden att anvrända sen # Hämta länkar för bilden att anvrända sen
#print(profile.viewing().prettify()) # _print(profile.container, user.username, profile.viewing().prettify())
for a in profile.viewing().find_all("a", href=True): for a in profile.viewing().find_all("a", href=True):
if all( if all(
[ [
@ -186,19 +220,21 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
"=R" not in a["href"], "=R" not in a["href"],
] ]
): ):
url_reactions = url_bas + str(a["href"]) # Länk till reaktionerna för bilden url_reactions = url_bas + str(
a["href"]
) # Länk till reaktionerna för bilden
elif a.text == "View full size": elif a.text == "View full size":
pic = url_bas + a["href"] pic = url_bas + a["href"]
picture.url_full = pic[ picture.url_full = pic[
: pic.find("&") : pic.find("&")
] # Den fullständiga adressen till bilden, används som _key i pictures ] # Den fullständiga adressen till bilden, används som _key i pictures
if 'url_reactions' not in locals(): if "url_reactions" not in locals():
for a in profile.viewing().find_all("a", href=True): for a in profile.viewing().find_all("a", href=True):
if '/likes/' in a["href"]: if "/likes/" in a["href"]:
url_reactions = url_bas + str(a["href"]) url_reactions = url_bas + str(a["href"])
if 'url_reactions' not in locals(): if "url_reactions" not in locals():
for div in profile.viewing().find_all("div", href=True): for div in profile.viewing().find_all("div", href=True):
if 'like this' in div.text: if "like this" in div.text:
url_reactions = url_bas + str(div["href"]) url_reactions = url_bas + str(div["href"])
# Hämta reaktioner för bilden # Hämta reaktioner för bilden
@ -213,11 +249,21 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
url_limit = a["href"] url_limit = a["href"]
picture.no_reactions = re.search(r"total_count=(\d+)", url_limit).group(1) picture.no_reactions = re.search(r"total_count=(\d+)", url_limit).group(1)
limit = re.search(r"limit=(\d+)", url_limit).group(1) # TODO Fortfarande problem med det här limit = re.search(r"limit=(\d+)", url_limit).group(
1
) # TODO Fortfarande problem med det här
except UnboundLocalError: # fel9 except UnboundLocalError: # fel9
write_error(9, soup=profile.viewing(), traceback=traceback.format_exc(), url=url_reactions, url_name='url_reactions') write_error(
9,
user=user,
profile=profile.container,
soup=profile.viewing(),
traceback=traceback.format_exc(),
url=url_reactions,
url_name="url_reactions",
)
# Bilder med väldigt många likes går inte att visa så här? # Bilder med väldigt många likes går inte att visa så här?
continue return None
# Addera bilden till arrango # Addera bilden till arrango
picture.add_to_db() picture.add_to_db()
@ -229,13 +275,12 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
try: try:
sleep_(4) sleep_(4)
profile.browser.open(url_limit) profile.browser.open(url_limit)
url_limit = '' url_limit = ""
update_cookie(profile.browser.session.cookies, profile.name) update_cookie(profile.browser.session.cookies, profile.name)
# Gå igenom alla som reagerat och för in i arango # Gå igenom alla som reagerat och för in i arango
for li in profile.viewing().find_all("li"): for li in profile.viewing().find_all("li"):
friend = Friend(user.username, mode) friend = Friend(user.username)
if "see more" in li.text.lower(): if "see more" in li.text.lower():
continue continue
try: try:
@ -260,28 +305,31 @@ def profile_picture_reactions(profile, user, all_pictures, first_user=False, mod
1, 1,
e=e, e=e,
soup=str(li), soup=str(li),
user=user.username, user=user,
profile=profile.container,
traceback=traceback.format_exc(), traceback=traceback.format_exc(),
) )
pass pass
# Lägg till reaktion till databasen # Lägg till reaktioner till databasen
db.collection("picture_reactions").insert_many( db.collection("picture_reactions").insert_many(
picture.reactions, silent=True, overwrite=True picture.reactions, silent=True, overwrite=True
) )
db.collection("picture_reactions").insert_many(picture.reactions, silent=True, overwrite=True) db.collection("picture_reactions").insert_many(
picture.reactions, silent=True, overwrite=True
)
# Uppdatera antalet reaktioner användaren fått
user.reactions += len(picture.reactions)
except Exception as e: # Fel2 except Exception as e: # Fel2
write_error( write_error(
2, 2,
e=e, e=e,
soup=profile.viewing(), soup=profile.viewing(),
user=user.username, profile=profile.container,
user=user,
url=url_limit, url=url_limit,
url_name="url_limit", url_name="url_limit",
traceback=traceback.format_exc(), traceback=traceback.format_exc(),
) )
pass pass
user.checked()
Loading…
Cancel
Save