代码之家  ›  专栏  ›  技术社区  ›  Sundararajan S

日志中最常见的3页序列

  •  3
  • Sundararajan S  · 技术社区  · 15 年前

    给定包含字段“用户”“页面url”的web日志。我们必须找出用户使用的最频繁的3页序列。

    6 回复  |  直到 15 年前
        1
  •  4
  •   Nick Johnson    15 年前

    假设日志是按时间戳顺序存储的,下面是一个算法,可以满足您的需要:

    1. 创建一个哈希表“用户访问量”,将用户ID映射到您观察到他们访问的最后两个页面
    2. 创建哈希表“visit_count”将页面的3元组映射到频率计数
      1. 如果有两个条目的用户访问中存在“user”,则将对应于三元组url的访问计数中的条目增加一个
      2. 将“URL”附加到用户访问中的相关条目,必要时删除最旧的条目。
    3. 按值对访问计数哈希表排序。这是你最流行的网址序列列表。

    下面是Python中的一个实现,假设您的字段是空格分隔的:

    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)
    
        2
  •  3
  •   jball    15 年前

    又快又脏:

    • 根据生成url/时间戳列表
    • 按时间戳对每个列表排序
    • 遍历每个列表
    • 在URL序列计数列表中查找最高计数

    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)
    
        3
  •  2
  •   Unreason    15 年前

    这里有一点SQL假设您可以将日志放入一个表中,比如

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

    ord column是日志文件中的行数)

    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;
    

    这将为用户提供前十个3停止路径。或者,如果您可以按用户和时间排序,则可以更轻松地加入行号。

        4
  •  1
  •   Dr. belisarius    15 年前

    s= { {user},{page} }  (* load List (log) here *)
    
    sortedListbyUser=s[[Ordering[Transpose[{s[[All, 1]], Range[Length[s]]}]] ]]
    
    Tally[Partition [sortedListbyUser,3,1]]
    
        5
  •  1
  •   Community CDub    8 年前

    这个问题与

    从文件中查找k个最常用的单词

    以下是解决方法:

        6
  •  1
  •   Xuelian Han    8 年前
    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);
    }