和陈正的msn聊天记录-关于搜索引擎
[18:06:49] zheng: :P
[18:06:49] zheng: 这动动 是不是不能留言的
[18:08:26] :P 搜索引擎-重新开始: ==
[18:10:28] :P 搜索引擎-重新开始: 来了
[18:11:00] zheng: 在忙工作吗?
[18:11:27] :P 搜索引擎-重新开始: 刚才在讨论问题
[18:11:44] :P 搜索引擎-重新开始: 刚才我看了一下,那个公司的确不怎么样
[18:12:05] zheng: http://www.baidu.com/hr/
[18:12:12] :P 搜索引擎-重新开始: 对了,你当时做spider的时候,抓取下来的页面怎么保存的?一个页面保存到一个文件嘛?
[18:12:34] zheng: 是的 我当时是如此
[18:12:44] zheng: 不过好象保存到一个文件里更好吧~
[18:12:49] :P 搜索引擎-重新开始: 为什么?
[18:13:10] :P 搜索引擎-重新开始: baidu,我爱
[18:13:20] :P 搜索引擎-重新开始: 支持
[18:13:45] zheng: 不会过多的打开文件 关闭文件啊~ 不过这个我们当时没讨论 没注意!
[18:14:18] :P 搜索引擎-重新开始: 你认为是io开关的效率低,还是线程的同步效率低?
[18:15:11] zheng: 开关~ 我只是认为可能 并不确定
[18:15:22] zheng: 还有创建文件
[18:15:43] :P 搜索引擎-重新开始: 什么意思?
[18:15:52] zheng: 因为页面一般都不大
[18:16:02] zheng: 如果是单个页面对应一个文件
[18:16:07] zheng: 会创建好多文件
[18:16:08] :P 搜索引擎-重新开始: 如果采用多线程的来写入io呢
[18:16:19] :P 搜索引擎-重新开始: 文件数量不是问题
[18:16:34] zheng: 至于创建文件有没开销 我也不清楚~
[18:17:17] zheng: 恩 可以!
[18:17:17] zheng: 可以这样
[18:17:28] zheng: 设置缓冲区~
[18:17:33] zheng: 多线写入
[18:17:52] :P 搜索引擎-重新开始: 然后有专门的io线程负责保存
[18:18:33] zheng: 不过可能又要碰到 缓冲区的 互斥 的问题
[18:18:54] zheng: 等下~
[18:19:03] :P 搜索引擎-重新开始: 我的
[18:19:13] zheng: 晕~
[18:19:13] :P 搜索引擎-重新开始: 波错了
[18:19:19] zheng: 等下回宿舍再打啊~
[18:19:31] zheng: :D
[18:19:43] :P 搜索引擎-重新开始: 对了你上次的hook怎么做的,纯cpp里面有事件的概念吗?
[18:19:46] :P 搜索引擎-重新开始: 没有吧
[18:20:02] zheng: 我大概说一下我那个下载部分的流程
[18:20:24] :P 搜索引擎-重新开始: 好的,
[18:25:19] :P 搜索引擎-重新开始: 好久啊,发过来看先
[18:25:35] zheng: 首先有一个未下载URL队列 UQ
然后开启多个线程从UQ中分别读出一定数量的URL(互斥读取)
各个线程分别下载读出的URL,下完一个,就写入文件一个
每个页面对应一个文件,线程内部是串行的 ,不考虑互斥
现在加上缓冲区,如果是针对每个下载线程都设置一个缓冲区,那就也不用考虑下载线程间的互斥。
[18:26:31] :P 搜索引擎-重新开始: 老大,你给我发个email好不?
[18:26:47] zheng: 发什么?
[18:26:56] :P 搜索引擎-重新开始: 你的设计思路
[18:27:08] :P 搜索引擎-重新开始: 然后开启多个线程从UQ中分别读出一定数量的URL?
[18:27:22] :P 搜索引擎-重新开始: 每个线程拥有一个url?
[18:28:16] zheng: 假设一开始的工作线程有一个队列保存一些 页面地址
然后就创建子线程序来下载啊
[18:29:03] :P 搜索引擎-重新开始: 创建多少个线程?
[18:29:06] :P 搜索引擎-重新开始: 子线程
[18:29:23] zheng: 我那里好象是 10 个吧~
[18:29:25] :P 搜索引擎-重新开始: 对了页面地址队列在哪里保存?
[18:29:49] :P 搜索引擎-重新开始: 子线程数量变化的吗?
[18:30:30] zheng: 我们只是 大概的弄出个 可以下载的东东 还没考虑其他的呢
[18:30:30] zheng: 现在是固定
[18:30:59] zheng: 反正还有好多好多要考虑的东西 我都没写入代码呢
[18:31:18] :P 搜索引擎-重新开始: 对了页面地址队列在哪里保存?
[18:31:24] :P 搜索引擎-重新开始: 你现在怎么处理的
[18:31:44] zheng:
/*————————————————————————————————————————————/
* Desc: 开始| 结束爬虫
* Parm
/————————————————————————————————————————————*/
bool cauc_crawler_manager::Start()
{
for(unsigned int i=0; i<m_pt_crawler_cont.size(); i++)
{
if(m_pt_crawler_cont[i])
m_pt_crawler_cont[i]->start_download();
}
return true;
}
[18:32:18] :P 搜索引擎-重新开始: m_pt_crawler_cont[i]是页面对象吗?
[18:32:33] zheng: 怎么把那些图片的快接见 去掉
[18:32:43] :P 搜索引擎-重新开始: 我也不知道也
[18:32:51] :P 搜索引擎-重新开始: 没关系的,我看的董
[18:33:18] :P 搜索引擎-重新开始: 每个子线程都维护一个自己的页面链接队列吗?
[18:33:55] zheng: 是的
[18:34:35] zheng: 不过下载完后 也是由子线程 分析页面(parser) 然后写回到 父线程的 URL 队列
(暂时是如此)
[18:34:42] :P 搜索引擎-重新开始: 就是说子线程负责完成自己维护的页面链接队列的搜索罗,那样会不公平哦,有些子线程会很清闲
[18:34:48] zheng: 互斥的写回
[18:35:19] zheng: 不是
[18:36:14] zheng: 子线程 负责 : 每次取一定的URL下载,写入文件,分析出新的URL,写回到父线程的URL
(下完后取过来的URL 后,继续循环)
[18:36:16] :P 搜索引擎-重新开始: 互斥的写回,什么意思
[18:36:55] :P 搜索引擎-重新开始: 嗯,想法对。消重是父进程的任务吧
[18:37:00] zheng: 因为多个线程并行的往 父线程的 URL 队列里加啊
[18:37:08] zheng: YES
[18:37:12] :P 搜索引擎-重新开始: 队对对,想法一样
[18:37:16] :P 搜索引擎-重新开始: (K)
[18:37:26] zheng: (H)
[18:38:28] zheng: 不过子线程应该还可以分一下 : 下载页面,写入IO,分析页面及写回~~ 应该分为两个线程
[18:38:48] :P 搜索引擎-重新开始: 嗯?链接的提取不是在内存中进行的吗?
[18:38:48] zheng: 我现在完成的还比较粗糙~~~
[18:38:58] zheng: 是
[18:39:25] :P 搜索引擎-重新开始: 那么Spider的抓取进行不应该负责写入IO了吧
[18:39:25] zheng: 还没些入文件时就要分析啊 ,总不能写了,再读吧。
[18:40:14] zheng: ?
[18:40:15] :P 搜索引擎-重新开始:
像我们刚才的说法,把字符写入缓存,然后由专门的IO进程负责写入,那么Spider的效率应该能够给你更高
[18:41:16] zheng: 下载页面,写入IO,分析页面及写回~~ 应该分为两个线程
[18:41:27] zheng: 分为两个: 通过缓冲区连接
[18:41:37] zheng: 一个负责下载并写入缓冲
[18:41:55] :P 搜索引擎-重新开始: 我的想法是这样:先定义几个类:
[18:43:49] :P 搜索引擎-重新开始: 1、SpiderController:
(相当于你的父线程),负责维护要搜索的链接列表,和消重;负责Spider线程的创建和销毁
[18:45:43] :P 搜索引擎-重新开始:
2、Spider:每次从SpiderControll的链接列表中获取一个链接,然后进行页面抓取(保存在缓存中),并负责
从缓存的字符流中提取出链接;把新链接提交给Controller后,返回Controller的闲置Spider队列
[18:46:31] :P 搜索引擎-重新开始: 3、Io类:专门负责从缓存中读取字符流写入文件,缓存可以设计成n级的
[18:46:36] zheng: 获取一个不好~
[18:46:57] :P 搜索引擎-重新开始: 为什么不好
[18:47:08] zheng: 差不多~
[18:47:35] zheng: 互斥次数会增加~
[18:47:38] :P 搜索引擎-重新开始:
Controller维护着一个Spider的线程队列,负责Spider的调度,这样肯定不会存在限制线程
[18:47:57] zheng: 多个线程的读 要互斥
[18:48:04] :P 搜索引擎-重新开始: 互斥只有一个地方,就是在写入缓存的时候
[18:48:09] zheng: 否则会同时读取一样的 URL
[18:48:36] zheng: 因为读后必须进行一些标记 或者说把被读的URL 弹出
[18:49:08] :P 搜索引擎-重新开始:
Controller是单线程,负责Spider的调度,所以不会出现几个Spider读取一样的url
[18:49:20] :P 搜索引擎-重新开始: 对啊,读以后就弹出了
[18:49:24] zheng: 你看我的 cauc_crawler.h
[18:49:26] :P 搜索引擎-重新开始: 好
[18:50:02] zheng: spider 是多个并发~
[18:50:23] :P 搜索引擎-重新开始: 嗯
[18:50:39] zheng: /*
* [下载线程函数]
**/
static
UINT download_thread(LPVOID lparam);
[18:50:41] :P 搜索引擎-重新开始: spider是你所说的子线吗?
[18:50:52] zheng: 相当于你说的 spider
[18:51:17] :P 搜索引擎-重新开始: 对啊,spider是并发的,不过要等controller调度啊
[18:51:30] :P 搜索引擎-重新开始: 调度的时候是逐个调度的,
[18:52:20] zheng: 调度相当于 让父亲分配URL 给 子线
[18:52:25] :P 搜索引擎-重新开始: right
[18:52:26] zheng: 还不如让子线主动取URL
[18:53:07] :P 搜索引擎-重新开始: 嗯,好主意,是说让子线到控制器的url队列中取链接是吧
[18:53:22] :P 搜索引擎-重新开始: 那样实现更简单了,只要做个锁就可以了
[18:53:27] zheng: 是的 这样就得互斥
[18:53:27] zheng: 对
[18:53:41] zheng: 所以每次取一个 就会频繁使用锁
[18:54:04] :P 搜索引擎-重新开始: (K),小子厉害。没关系,给你10个一次
[18:54:14] zheng: 如果每次取某个(经验数字 哈) 就会减少。
[18:54:25] zheng: :P
[18:55:13] zheng: 不过我没把控制和子分开,因为我的子线还没细化。 现在就想当于 cauc_crawler
中的那个静态函数
[18:55:37] :P 搜索引擎-重新开始: (}),基本上思路我已经有了,不过现在就是消重和IO的问题。.net 的io怎么样,效率
[18:56:24] zheng: 不清楚的说~ 不过.net 的网络下载那快就比较好写~
[18:56:51] :P 搜索引擎-重新开始: 呵呵,哪些不是问题,而且也我们只会用socket,也想不到什么改进的方法
[18:56:58] zheng: 反正我也要改,并把代码整理下 ,以后找工作可以拿出来见人啊……
[18:56:58] zheng: 哈~
[18:57:05] :P 搜索引擎-重新开始: 不过我还是用vc写,呵呵,
[18:57:54] :P 搜索引擎-重新开始: 这两天海南又要台风了,
[18:58:09] zheng: 消重 我可能自己写一个来解决URL 的存储以及消重
[18:58:20] zheng: 键树
[18:58:26] :P 搜索引擎-重新开始: 写好了吗?
[18:58:31] zheng: 不过额外空间非常大
[18:58:41] zheng: 呵呵 写好了 那我不笑了~
[18:58:50] :P 搜索引擎-重新开始: ???
[18:59:01] zheng: 我以前就在计划着写这个 一直想不出很好的方案
[18:59:24] zheng: 键数的消重 时间复杂度是 N (URL 的字符个数)
[18:59:38] :P 搜索引擎-重新开始: 嗯,好
[18:59:44] zheng: 不过额外的空间就太多了 指针~
[18:59:58] :P 搜索引擎-重新开始: 呵呵,有些变态的url
[19:00:37] zheng: 就是一个节点有(假设 URL 的合法字符个数 80) 80 个指针
[19:00:40] :P 搜索引擎-重新开始: 对了,有没有纯cpp的hook的实现方法
[19:01:06] zheng: 一个节点的数据却只有一个字符
[19:01:20] zheng: 什么?
[19:01:26] zheng: 什么的 hook?
[19:01:32] :P 搜索引擎-重新开始: 匹配的时候按深度优先?
[19:01:43] :P 搜索引擎-重新开始: 相当于event的东西
[19:01:49] :P 搜索引擎-重新开始: 钩子啊
[19:01:53] zheng: 不是~
[19:02:24] zheng: 钩子 用来做什么的? WINDOWS 的钩子吗?
[19:02:52] :P 搜索引擎-重新开始: 对,实现类似windows钩子一样的机制
[19:02:52] zheng: 键树 你就忘记了 8o|
[19:03:07] :P 搜索引擎-重新开始: 呵呵,靠研都不靠的啊
[19:03:13] zheng: 我的PARSER 就是类似的机制啊 哈哈
[19:03:40] :P 搜索引擎-重新开始: 这个机制叫observer设计模式
[19:04:06] zheng: 观察者? 呵
[19:04:59] :P 搜索引擎-重新开始: 哈,慢慢来把,我先看过你的代码先,然后在结合我的方法给你一个email,
[19:05:19] zheng: 键树是这样 一个节点 80个字符(暂时为80) + 一个数据(字符)
[19:05:30] zheng: 80个指针(说错了)
[19:05:42] :P 搜索引擎-重新开始: 继续
[19:05:48] zheng: 如果有URL sina.com
[19:06:43] zheng: 给合法的80个字符编号(随便编了)
假设
s 3
i 6
n 5
a 2
. 8
c 22
o 66
m 77
[19:07:35] zheng: 则第一个节点的第3个指针 new 得到一个新的节点数据 N1
[19:07:55] zheng: N1 节点的第6个指针 new 得到 N2
[19:08:07] :P 搜索引擎-重新开始: 第一个节点保存什么字符
[19:08:17] zheng: 同理 继续到 m
[19:08:28] zheng: 没保存
[19:08:47] zheng: 到第 m 个 时把该为数据 设置为 1
[19:09:04] zheng: new 的时候假设全设置为0
[19:09:05] :P 搜索引擎-重新开始: 1代表?
[19:09:18] :P 搜索引擎-重新开始: 0代表叶子?
[19:09:18] zheng: 1 表示到此节点的串存在
[19:09:40] zheng: 0 代表不存在该串
[19:10:02] :P 搜索引擎-重新开始: 那现在来了sina.comm呢
[19:10:34] zheng: 因为m 的指针域都是空 ~~
[19:11:27] zheng: 刚才 在 o 节点的时候 ,在第77 个指针 new 一个 pt_obj
[19:11:59] zheng: 然后把 pt_obj 中的那个位设置为 1 表示 串结束
[19:12:17] zheng: 此时 pt_obj 中的80个指针域 还是 NULL
[19:12:31] zheng: 如果判断 sina.comm 是否存在
[19:12:38] :P 搜索引擎-重新开始: pt_obj 中的那个位设置为 1
就是一个节点 80个指针(暂时为80) + 一个数据(字符)
的数据吧?
[19:12:47] :P 搜索引擎-重新开始: 数据置为1吧
[19:12:57] zheng: 那么 根据 pt_obj 的第 77 个指针域 pt_77
[19:13:11] zheng: 对啊~
[19:13:13] :P 搜索引擎-重新开始: 看看是否为空?
[19:13:31] zheng: 根据 pt_77 是否为 NULL 如果不为NULL 则判断 pt_77 是否数据为1来判断
[19:14:01] zheng: 额外负担(指针) 非常重
[19:14:03] :P 搜索引擎-重新开始: 明白了,小子厉害,不过额外空间的确很大,不过搜索起来会很快,对了
[19:14:17] :P 搜索引擎-重新开始: 怎么知道s对应的是那个指针
[19:14:27] :P 搜索引擎-重新开始: ?
[19:14:29] :P 搜索引擎-重新开始: ascii?
[19:14:38] zheng: 不是
[19:14:45] :P 搜索引擎-重新开始: how
[19:15:04] zheng: URL 的合法字符 不过100 个 自己设置
[19:15:27] zheng: 然后通过某函数 get_index ( char ) 得到
[19:15:47] zheng: get_char( int ) 还原
[19:15:51] :P 搜索引擎-重新开始: 呵呵,又是这样的方法。你是不是保存一个全局数组啊
[19:16:00] :P 搜索引擎-重新开始: 保存字符-数字的映射的
[19:16:57] zheng: 对啊 ~ 不是全局 只要在哪个类负责 URL 消重 哪里就存在~ 一个这样的对象~ 或者 数组
[19:17:19] zheng: 存储是问题之一
[19:17:40] :P 搜索引擎-重新开始: 有没有比较过和哈希的效率差别
[19:18:09] zheng: 无所谓,反正在那两个函数里实现就行了~ 对吧
[19:18:20] :P 搜索引擎-重新开始: 对啊,兄弟,这个任务就交给你了
[19:18:24] :P 搜索引擎-重新开始: 比较一下效率,
[19:18:55] :P 搜索引擎-重新开始: 不过拿url来哈希,呵呵,。。。,鄙视~~
[19:19:20] zheng: ?
[19:19:20] zheng: 啊
[19:19:31] zheng: 你是说URL 哈希啊
[19:20:02] zheng: 好象有问题的~
[19:20:12] zheng: 不过肯定的是 URL 哈希 肯定不如 键树
[19:20:39] :P 搜索引擎-重新开始: 呵呵,好好好。不过这次我要做的搜索引擎比较special
[19:21:16] zheng: 哈希 是全局是的 lg n
[19:21:46] zheng: 比如 待匹配的 URL p
[19:21:51] zheng: 平均同 lg n 个 URL 比较
[19:22:21] zheng: 而 没一次的比较 可能比较 n ( 0<n< URL 长度) 次
[19:22:43] :P 搜索引擎-重新开始: 嗯,晓得。不过你的键树怎么标识没有子节点?
[19:22:56] zheng: 指针为空
[19:22:56] :P 搜索引擎-重新开始: 没必要
[19:23:11] zheng: ?
[19:23:34] :P 搜索引擎-重新开始: 不是不是,我刚才晕了
[19:23:53] zheng: :P
[19:24:06] zheng: 如果有这个存储 URL 就必须实现另外一个
[19:24:24] :P 搜索引擎-重新开始:
好方法。不过这次我主要做的是parser,是对特定模板页面的内容提取,比如说这个网页上提取标题和作者
[19:24:29] zheng: 能动态的 在本地磁盘 和 内存间切换
[19:24:36] zheng: 那容易啊
[19:24:46] zheng: 用我的
[19:24:46] zheng: 我的通用
[19:24:48] zheng: 只要改 hook 就行
[19:24:59] :P 搜索引擎-重新开始: 对啊,就是parser要改,
[19:25:10] :P 搜索引擎-重新开始: 问题是有很多个不同的模板
[19:25:29] :P 搜索引擎-重新开始: 不过我已经想到实现的方法了,我们合作写篇论文吧
[19:25:35] zheng: 什么意思?
[19:25:44] zheng: 好啊
[19:25:57] zheng: 只要改 HOOK 就行了啊
[19:26:09] :P 搜索引擎-重新开始: 你的hook是?
[19:26:15] zheng: 不管什么 tab 都会被我的 parser 提取
[19:26:28] zheng: 而我的 hook 是 选择需要的 tab 的数据 进行处理
[19:26:57] :P 搜索引擎-重新开始: 呵呵,现在不是获取tag,是获取在页面中的某个内容,可能出现在哪个table中,
[19:27:16] :P 搜索引擎-重新开始: 可是内容没有标记啊
[19:27:25] zheng: 那你如何判断 是标题?
[19:27:45] zheng: 不会是 传说中的数据挖掘吧~
[19:27:47] :P 搜索引擎-重新开始: 呵呵,现在只能以不同的页面做不同的模板,进行匹配,提取信息
[19:28:09] :P 搜索引擎-重新开始: 数据挖掘我还没能力啊,但是这其实就是数据挖掘的内容
[19:28:14] zheng: table 也是一个 tab 啊
[19:28:27] :P 搜索引擎-重新开始: 弱智吧,嘲笑我吧。
[19:28:43] zheng: hook 一对table 处理就行了 ~……?
[19:28:53] zheng: 8o|
[19:29:16] :P 搜索引擎-重新开始: 我今天高兴把内容放在第一个table
的“看看的后面:标题”,明天放在第二个table“笑笑:标题”,那怎么办?
[19:29:49] :P 搜索引擎-重新开始: 如果她那么好<这里是标题>标题内容</这里是标题>,那就不用考虑那么多了
[19:30:00] zheng: Core\html_parser
[19:30:05] zheng: 里是我的 分析器~
[19:30:07] :P 搜索引擎-重新开始: 什么东西?
[19:30:26] zheng: 页面分析的代码
[19:30:36] :P 搜索引擎-重新开始: 好,我回去好好看看,今天聊的很high,突然有幸趣写篇论文。轻量级搜索引擎的实现
[19:30:56] zheng: :P
[19:31:06] :P 搜索引擎-重新开始: 你负责spider,我负责parser,然后实现在c++和.net平台上的移植
[19:31:37] :P 搜索引擎-重新开始: 只要功能上能够满足企业特定内容的检索就好了,不作通用的搜索引擎
[19:31:52] zheng: 恩
[19:31:56] :P 搜索引擎-重新开始: 做通用的不如找nutch或者lucene
[19:32:01] zheng: 问题是这个是 spider 而已啊
[19:32:23] :P 搜索引擎-重新开始: 慢慢来吗,反正我有那么高热情,你有那么好技术
[19:32:49] zheng: :P 别夸奖!
[19:33:17] :P 搜索引擎-重新开始: :P,唉,该夸的时候就该夸,小子厉害啊
All the posts in this blog are provided "AS IS" with no warranties, and confer no rights. Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution 2.5 China Mainland License.