2010-06-07 4 views
3

Compte tenu d'un journal Web qui se compose des champs 'User' 'Page url'. Nous devons trouver la séquence de 3 pages la plus fréquente que les utilisateurs prennent.Séquence la plus fréquente de 3 pages dans un weblog

Il existe un horodatage. et il n'est pas garanti que l'accès utilisateur unique sera enregistré séquentiellement il pourrait être comme user1 Page1 user2 Pagex utilisateur1 Page2 Utilisateur10 Pagex user1 Page 3 sa séquence de page User1s est page1-> page2-> page 3

+0

sont des éléments garantis à ajouter afin d'accès, ou est-il un horodatage aussi bien ? – jball

+0

comment votre journal est-il stocké? –

+0

Il existe un horodatage. et il est pas garanti que l'accès par un seul utilisateur sera connecté de manière séquentielle il pourrait être comme user1 Page1 utilisateur2 Pagex user1 Page2 Utilisateur10 Pagex user1 Page 3 sa User1s séquence de page est page1-> page2-> Page 3 –

Répondre

3

Rapide et sale:

  • construire une liste d'URL/horodatages par utilisateur
  • trier chaque liste par horodatage
  • itérer sur chaque liste
    • pour chaque 3 URL seque nce, créer ou incrémenter un compteur
  • trouver le plus grand nombre dans le décompte séquence URL liste

foreach(entry in parsedLog) 
{ 
    users[entry.user].urls.add(entry.time, entry.url) 
} 

foreach(user in users) 
{ 
    user.urls.sort() 
    for(i = 0; i < user.urls.length - 2; i++) 
    { 
     key = createKey(user.urls[i], user.urls[i+1], user.urls[i+2] 
     sequenceCounts.incrementOrCreate(key); 
    } 
} 

sequenceCounts.sortDesc() 
largestCountKey = sequenceCounts[0] 
topUrlSequence = parseKey(largestCountkey) 
+0

Aurait besoin d'un meilleur algorithme de temps et de mémoire efficace –

+0

Combien de mieux? Encore une fois, combien d'entrées de journal et d'URL possibles y a-t-il? – jball

+0

Veillez à ce que chaque URL participe à 3 listes (dans la première dans l'ordre trois, dans la deuxième dans l'ordre deux et dans la troisième dans l'ordre un) –

1

code source dans Mathematica

s= { {user},{page} } (* load List (log) here *) 

sortedListbyUser=s[[Ordering[Transpose[{s[[All, 1]], Range[Length[s]]}]] ]] 

Tally[Partition [sortedListbyUser,3,1]] 
2

Voici un peu de SQL en supposant que vous pourriez obtenir votre journal dans une table telle que

CREATE TABLE log (
    ord int, 
    user VARCHAR(50) NOT NULL, 
    url VARCHAR(255) NOT NULL, 
    ts datetime 
) ENGINE=InnoDB; 

Si les données ne sont pas triées par utilisateur alors (en supposant que ord colonne est le numéro de la ligne du fichier journal)

SELECT t.url, t2.url, t3.url, count(*) c 
FROM 
     log t INNER JOIN 
     log t2 ON t.user = t2.user INNER JOIN 
     log t3 ON t2.user = t3.user 
WHERE 
     t2.ord IN (SELECT MIN(ord) 
       FROM log i 
       WHERE i.user = t.user AND i.ord > t.ord) 
     AND 
     t3.ord IN (SELECT MIN(ord) 
       FROM log i 
       WHERE i.user = t.user AND i.ord > t2.ord) 
GROUP BY t.user, t.url, t2.url, t3.url 
ORDER BY c DESC 
LIMIT 10; 

Cela donnera dix meilleurs 3 chemins d'arrêt pour un utilisateur. Alternativement, si vous pouvez l'obtenir commandé par l'utilisateur et le temps, vous pouvez vous joindre à des rownumbers plus facilement.

4

En supposant que votre journal est stocké dans l'ordre d'horodatage, voici un algorithme pour faire ce que vous avez besoin:

  1. Créer un utilisateur mapping Hashtable « user_visits » ID aux deux dernières pages que vous les ai observés à visiter
  2. Créer une application « de VISIT_COUNT » Hashtable 3 triplets de pages à Comptes de fréquences
  3. Pour chaque entrée (utilisateur, URL) dans le journal:
    1. Si « utilisateur » existe dans user_visits avec deux entrées, incrémenter l'entrée en visite _count correspondant au 3-uplet d'URL par un
    2. Ajoutez 'URL' à l'entrée correspondante dans user_visits, en supprimant l'entrée la plus ancienne si nécessaire.
  4. Trier la table de hachage visit_count par valeur. Voici votre liste des séquences d'URL les plus populaires.

est ici une implémentation en Python, en supposant que vos champs sont espace séparés:

fh = open('log.txt', 'r') 
user_visits = {} 
visit_counts = {} 
for row in fh: 
    user, url = row.split(' ') 
    prev_visits = user_visits.get(user,()) 
    if len(prev_vists) == 2: 
    visit_tuple = prev_vists + (url,) 
    visit_counts[visit_tuple] = visit_counts.get(visit_tuple, 0) + 1 
    user_visits[user] = (prev_vists[1], url) 
popular_sequences = sorted(visit_counts, key=lambda x:x[1], reverse=True) 
+0

Pourriez-vous ou quelqu'un d'autre expliquer ce que "user_visits.get (utilisateur,())" est censé retourner? Quelques-unes des autres lignes pourraient également utiliser le commentaire :) – Organiccat

+0

@Organiccat '.get' est un appel de bibliothèque standard Python sur dict; il renvoie la valeur correspondant à la clé dans le premier argument s'il existe dans la dict, et renvoie le second argument si ce n'est pas le cas. '()' est un idiome Python pour un Tuple vide. –

1

Ce problème est similaire à

Trouvez k mots les plus fréquents d'un fichier

Voici comment vous pouvez le résoudre:

  • groupe chaque triplet (page1, page2, page3) en un mot
  • Appliquer l'algorithme mentionné here
1
1.Reads user page access urls from file line by line,these urls separated by separator,eg: 
u1,/ 
u1,main 
u1,detail 

The separator is comma. 
2.Store each page's visit count to map:pageVisitCounts; 
3.Sort the visit count map by value in descend order; 

public static Map<String, Integer> findThreeMaxPagesPathV1(String file, String separator, int depth) { 
    Map<String, Integer> pageVisitCounts = new HashMap<String, Integer>(); 
    if (file == null || "".equals(file)) { 
     return pageVisitCounts; 
    } 
    try { 
     File f = new File(file); 
     FileReader fr = new FileReader(f); 
     BufferedReader bf = new BufferedReader(fr); 

     Map<String, List<String>> userUrls = new HashMap<String, List<String>>(); 
     String currentLine = ""; 
     while ((currentLine = bf.readLine()) != null) { 
      String[] lineArr = currentLine.split(separator); 
      if (lineArr == null || lineArr.length != (depth - 1)) { 
       continue; 
      } 
      String user = lineArr[0]; 
      String page = lineArr[1]; 
      List<String> urlLinkedList = null; 
      if (userUrls.get(user) == null) { 
       urlLinkedList = new LinkedList<String>(); 
      } else { 
       urlLinkedList = userUrls.get(user); 
       String pages = ""; 
       if (urlLinkedList.size() == (depth - 1)) { 
        pages = urlLinkedList.get(0).trim() + separator + urlLinkedList.get(1).trim() + separator + page; 
       } else if (urlLinkedList.size() > (depth - 1)) { 
        urlLinkedList.remove(0); 
        pages = urlLinkedList.get(0).trim() + separator + urlLinkedList.get(1).trim() + separator + page; 
       } 
       if (!"".equals(pages) && null != pages) { 
        Integer count = (pageVisitCounts.get(pages) == null ? 0 : pageVisitCounts.get(pages)) + 1; 
        pageVisitCounts.put(pages, count); 
       } 
      } 
      urlLinkedList.add(page); 
      System.out.println("user:" + user + ", urlLinkedList:" + urlLinkedList); 
      userUrls.put(user, urlLinkedList); 
     } 
     bf.close(); 
     fr.close(); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return pageVisitCounts; 
} 

public static void main(String[] args) { 
    String file = "/home/ieee754/Desktop/test-access.log"; 
    String separator = ","; 
    Map<String, Integer> pageVisitCounts = findThreeMaxPagesPathV1(file, separator, 3); 
    System.out.println(pageVisitCounts.size()); 
    Map<String, Integer> result = MapUtil.sortByValueDescendOrder(pageVisitCounts); 
    System.out.println(result); 
} 
+0

Bien que ce fragment de code puisse résoudre la question, [y compris une explication] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) aide vraiment à améliorer la qualité de votre message. Rappelez-vous que vous répondez à la question pour les lecteurs dans le futur, et que ces personnes pourraient ne pas connaître les raisons de votre suggestion de code. – DimaSan

Questions connexes