<jupyter_start><jupyter_text>Warm-up: 5 Esercizi in 30 minuti (in media) Esercizio 1A partire dalla lista _inizio_ si crei una nuova lista i cui elementi corrispondono alle lunghezze di ogni singola stringa nella lista.```Output: [2, 6, 9, 8, 1, 9, 5, 6, 3, 10, 2, 5]```<jupyter_code>inizio = ['in','questo','esercizio','contiamo','i','caratteri','delle','parole','che','compongono','la','lista']
# Modo Python Base
out = []
for e in inizio:
    out.append(len(e))
print(out)

# Modo Python intermedio = List comprehension
out_2 = [len(e) for e in inizio]<jupyter_output>[2, 6, 9, 8, 1, 9, 5, 6, 3, 10, 2, 5]<jupyter_text>Esercizio 2Si crei una stringa partendo dalla lista inizio composta dalla concatenazione delle parole contenute nella lista separate da uno spazio. Si utilizzi il metodo **join**```Output: 'in questo esercizio contiamo i caratteri delle parole che compongono la lista'```<jupyter_code>' '.join(inizio)<jupyter_output><empty_output><jupyter_text>Esercizio 3Si legga il file in formato JSON 'data/warmup.json' e si acceda al valore associato alla chiave _esercizio_ ```Output: Esercizio 5```<jupyter_code>json.load(open('data/warmup.json'))['esercizio']<jupyter_output><empty_output><jupyter_text>Esercizio 4Si crei un dictionary composto dalle chiavi 'uno', 'due' e 'tre' inizializzati al valore 0. Si implementi, poi un ciclo for di 10 iterazioni che incrementi i valori associati alle tre chiavi```Output: {'uno':10, 'due':10, 'tre':10}```<jupyter_code>d = {'uno':0, 'due':0, 'tre':0}
for i in range(10):
    d['uno'], d['due'], d['tre'] = d['uno'] + 1, d['due'] + 1, d['tre'] + 1
print(d)

d2 = {e:0 for e in ['uno','due','tre']}
d2<jupyter_output>{'uno': 10, 'due': 10, 'tre': 10}<jupyter_text>Esercizio 5Si estragga il valore associato alla chiave _esecizio_ nel file 'data/warmup.json' utilizzando solo i metodi della classe _string_```Output: Esercizio 5```<jupyter_code>with open('data/warmup.json') as f:
    js = f.read()
js_1 = js[js.index('esercizio')+len('esercizio: ')+2:]
js_2 = js_1[:js_1.index(',')-1]
print(js_2)

# Singola riga
js[js.index('esercizio": "')+len('esercizio": "') : js.index('",',js.index('esercizio":'))]<jupyter_output>Esercizio 5<jupyter_text>Esercizio 6Il file 'data/test.js' contiene un breve script in Javascript. Si estragga la lista Javascript e la si trasformi in una lista Python utilizzando il modulo **json**```Output: [2,4,5,6,3,2,5,4,3]```<jupyter_code>with open('data/test.js') as f:
    jsf = f.read()
lista = json.loads(jsf[jsf.index('['):jsf.index(']')+1])
print(type(lista), lista)<jupyter_output><class 'list'> [2, 4, 5, 6, 3, 2, 5, 4, 3]<jupyter_text>Esercizio 7Si scarichi la pagina www.google.it e si conti quante volta la stringa 'Google' occorre nella pagina```Output: 7 (puo' variare)```<jupyter_code>requests.get('https://www.google.it').text.count('Google')<jupyter_output><empty_output><jupyter_text>Esercizio 8Si richieda la risorsa associata all'URL https://postman-echo.com/get?foo1=bar1&foo2=bar2 e si ottega la stringa associata alla chiave _cookies_```Output:```<jupyter_code>requests.get('https://postman-echo.com/get?foo1=bar1&foo2=bar2').json()['headers']['user-agent']<jupyter_output><empty_output><jupyter_text>Esercizio 9Si esegua una richiesta HTTP con il metodo POST alla risorsa https://postman-echo.com/post inviando le chiavi 'nome' e 'cognome', a cui corrispondono nome e cognome dello studente. Si acceda al campo 'form' della risposta.```Output:```<jupyter_code>requests.post('https://postman-echo.com/post', data = {'nome': 'Toto', 'cognome': 'Cotugno'}).json()['form']<jupyter_output><empty_output><jupyter_text>Esercizio 10Si scarichino le slides della prima lezione disponibili qui - http://someni.di.unimi.it/slide/2018/Introduzione%20al%20corso.pdf - salvandole nel file 'primaLezione.pdf'.```Output:```<jupyter_code>with open('primaLezione.pdf','wb') as f:
    f.write(requests.get('http://someni.di.unimi.it/slide/2018/Introduzione%20al%20corso.pdf').content)

f = open('primaLezione2.pdf','wb')
f.write(requests.get('http://someni.di.unimi.it/slide/2018/Introduzione%20al%20corso.pdf').content)
f.close()<jupyter_output><empty_output><jupyter_text>EsercitazioneIn questa esercitazione utilizzeremo le nozioni presentate nella lezione di laboratorio "Web Scraping" applicandole al social media WANELO (https://wanelo.co/), un social media rivolto allo shopping e alla moda.Gli obiettivi dell'esercitazione sono  i seguenti:- loggarsi nel sistema attraverso il modulo **requests**- estrarre gli oggetti per uomo messi in vendita nella sezione 'Trending'- estrarre i folllower/following di un utente Passo 0Il primo passo è iscriversi al social media. E' possibile registrarsi a WANELO all'indirizzo https://wanelo.co/users/sign_in e cliccando sul link "Not a member yet? Join us!". Per registrarsi vi vengono richiesti un'indirizzo e-mail, uno username e una password (da non dimenticare). Obiettivo 1: Effettuare il login nel sistemIl form di login è raggiungibile all'indirizzo https://wanelo.co/users/sign_in a) Ispezionare il codice del formCliccare col tasto destro sul form di login e selezionare "Ispeziona". Si apre la console di Chrome. Selezionare il tab "Elements" se non è gia selezionato. Il file *form_login.html* contiene il codice del form.Analizzando il codice HTML si completino le seguenti celle di codice:- Qual è l'url a cui vengono inviati i dati del form?<jupyter_code>url_action = 'https://wanelo.co/users/sign_in'<jupyter_output><empty_output><jupyter_text>- Quanti sono i campi input? Quanti sono hidden? Quali sono i loro nomi? Quali sono i valori associati?<jupyter_code>input_data = {'utf8':'&#x2713;',
             'authenticity_token':'',
              'user[login]': 'USERNAME',
              'user[password]': 'PASSWORD',
              'user[remember_me]': 'true',
              'commit': 'Sign in'
             }<jupyter_output><empty_output><jupyter_text>ImprevistoRispetto al form visto a lezione, il campo authenticity_token ha un valore non definito ('XXXXXX'). Il valore associato all'attributo viene caricato dinamicamente.Utilizzando i DevTools di Chrome (tab 'Network') e il codice HTML della pagina https://wanelo.co/users/sign_in ( CTRL+U in Chrome per ottenere il codice sorgente della pagina) si puo' comprendere come ottenere il valore associato all'attributo *authenticity_token*. Una volta capito come ottenere il valore, si crei un oggetto Session:**N.B.** Tutte le richieste devono essere effettuate attraverso  l'oggetto Session creato<jupyter_code>sessione_wanelo = requests.Session()
sessione_wanelo.headers.update({'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36',
                               'DTN':'1',
                               'Referer':'https://wanelo.co/users/sign_in'})<jupyter_output><empty_output><jupyter_text>Si richieda la pagina di login indicata nelle precedenti istruzioni. La variabile sign_in_page deve contenere il testo (non utilizzare l'attributo content ma **text**) della pagina di login:<jupyter_code>sign_in_page = sessione_wanelo.get('https://wanelo.co/users/sign_in').text<jupyter_output><empty_output><jupyter_text>Si trasformi il testo della pagina in un oggetto BeautifulSoup:<jupyter_code>sign_in_albero = bs(sign_in_page,'lxml')<jupyter_output><empty_output><jupyter_text>Si estragga il valore da assegnare al campo *authenticity_token*:<jupyter_code>input_data['authenticity_token'] = sign_in_albero.find('meta',{'name':'csrf-token'}).attrs['content']<jupyter_output><empty_output><jupyter_text>b) Loggarsi nel sistemaUna volta individuato l'url e i parametri da inviare si deve inviare una richiesta HTTP di tipo POST all'url individuato Si esegua la richiesta HTTP. In caso di login corretto si deve ricevere una risposta con codice 200<jupyter_code>sessione_wanelo.post(url_action, data=input_data, allow_redirects=False).cookies.get_dict()<jupyter_output><empty_output><jupyter_text>Per verificare se l'utente è effettivamente loggato, cerchiamo se la stringa corrispondente al nostro username è presente nella pagina https://wanelo.co/username<jupyter_code>test_page = sessione_wanelo.get('https://wanelo.co/settings').text
if 'matteo_zignani' in test_page:
    print('Non ci sono problemi')
else:
    print('Problema')<jupyter_output>Problema<jupyter_text>Obiettivo 2: Estrarre gli oggetti nella sezione 'Trending' per la categoria "home"Per raggiungere il secondo obiettivo si procede con l'estrazione degli oggetti messi in vendita nella sezione 'Trending' https://wanelo.co/trending?c=home. Attraverso il parametro 'c' si specifica che si vogliono gli oggetti della categoria "home". a) individuare il valore dell'attributo class attraverso il quale posso identificare il tag div che contiene le informazioni dell'oggetto messo in venditaSi ispezioni il codice HTML della pagina https://wanelo.co/trending?c=home attraverso la funzione **Inspect** di Chrome.Una volta individuato il valore dell'attributo 'class', si estraggano le seguenti informazioni:- il nome dell'oggetto (evidenziato in rosso)- l'utente che ha postato l'oggetto (evidenziato in verde)- il negozio che mette in vendita l'oggetto (evidenziato in azzuro)- il prezzo dell'oggetto (evidenziato in giallo)- quante volte e' stato salvato l'oggetto (evidenziato in viola) b) la funzione get_infoSi implementi la funzione **get_info** che restituisce un dictionary costituito da cinque chiavi: - item - user- shop- price- saved La funzione riceve come unico argomento l'elemento div individuato al punto 2.a<jupyter_code>def get_info(div_item):
    out = dict()
    out['item'] = div_item.find('div',{'class':'name'}).a.text
    try:
        out['user'] = div_item.find('div',{'class':'poster'}).a.attrs['href'][1:]
    except AttributeError:
        pass
    out['shop'] = div_item.find('div',{'class':'store'}).a.attrs['href'][1:]
    out['price'] = div_item.find('div',{'class':'store'}).span.text
    out['saved'] = div_item.find('span',{'class':'js-saves-count'}).text
    return out<jupyter_output><empty_output><jupyter_text>c) Richiesta della pagina dei trendingSi richieda la pagina degli oggetti per uomo nella sezione 'Trending'<jupyter_code>trending_page = bs(sessione_wanelo.get('https://wanelo.co/trending?c=home').text,'lxml')<jupyter_output><empty_output><jupyter_text>d) il ciclo di estrazioneSi iteri sui tag 'div' individuati al punto 2.a e si estraggano le informazioni utilizzando la funzione precedentemente definita. Ogni dictionary restituito deve essere inserito in una lista 'item_info'<jupyter_code>item_info = []
for element in trending_page.findAll('div',{'class':'product-card'}):
    info = get_info(element)
    item_info.append(info)<jupyter_output><empty_output><jupyter_text>e) Costruzione dell'insieme dei nodi (seed) da cui far partire la visita della rete socialeSi crei una lista di url di utenti partendo dalle informazioni contenute in 'item_info'. Per esempio, da una entry del tipo ```python{    'user': 'pippo'    'item' : 'Lampada Ikea Akldskps'}```viene generato l'URL https://wanelo.co/pippo. Per eliminare eventuali ripetizioni si utilizzi il costruttore **set()** per costruire un insieme ricevendo come argomento una lista.<jupyter_code>seed = set(['https://wanelo.com/'+element['user'] for element in item_info if 'user' in element])<jupyter_output><empty_output><jupyter_text>Obiettivo 3: Estrarre i follower di un utentePer completare il terzo obiettivo dobbiamo estrarre i follower di un utente. In particolare, per ogni follower dobbiamo identificare il suo account name, ossia l'url del profilo dell'utente in Wanelo (es. https://wanelo.co/dg424). a) Identificare il valore dell'attributo class del tag 'div' che include le informazioni di un singolo followerAprire l'url che restituisce i follower di un utente, scelto in modo casuale; per esempio, https://wanelo.co/dg424/followers.Ispezionare il codice della pagina per trovare il tag 'div' che contiene le informazioni di un singolo follower. Il codice HTML è riportato anche nel file 'follower-item.html' b) Implementare la funzione get_followers()La funzione **get_followers** riceve come argomento l'account name e restituisce una lista deli followers (account name). Il numero massimo di followers ottenibili e' 60.<jupyter_code>def get_followers(session, username, max_followers = 60):
    followers = []
    page = bs(session.get(username+'/followers').text,'lxml')
    count = 2
    while len(followers) < max_followers:
        search = page.findAll('div',{'class':'followable-resource'})
        if search:
            for element in search:
                followers.append(element.find('a',{'class':'preview-strip-description-avatar'}).attrs['href'][1:]) 
            page = bs(session.get(username+'/followers/'+str(count)).text,'lxml')
            count += 1
        else:
            break
    return followers
test = get_followers(sessione_wanelo,'https://wanelo.co/dg424')<jupyter_output><empty_output><jupyter_text>c) Per ogni utente nel seed si ottengano i followers... utilizzando la funzione definita in precedenza<jupyter_code>followers_per_users = {username : get_followers(sessione_wanelo,username) for username in seed}<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12097870412324423, 'fraction_numerical': 0.014499320344358859, 'mean_word_length': 5.70871327254306, 'pattern_counts': {'":': 3, '<': 94, '<?xml version=': 0, '>': 93, 'https://': 22, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '24', 'dir': 'jupyter-structured-clean-dedup', 'id': '603852', 'license': 'MIT', 'n_tokens_mistral': 4806, 'n_tokens_neox': 4692, 'n_words': 1269, 'path': 'Esercitazione Guidata sul Web Scraping.ipynb', 'repo_name': 'matzigno/SocialMediaMining2019', 'size': '13242'}