我的需求很简单,我想从数据库读出url网页地址,读取过的不能再读,然后抓取网页源码,抓取完然后再存回去,url记录大约有十万
条,请问各位高手,我应该怎么样做呢?我的思路是开一个线程,读过的再把它一个字段如isReaded修改为1,再开几个线程去抓取。但问
题是:怎么样读取数据好呢,不能一下就读十万吧。读出来数据怎么放让另外的线程去读的?刚才试了下,一边读一边更新isReaded字
段,读取3000条时就报Network error IOException: Address already in use: connect 异常,也不知道是什么原因。还有怎么样才能做
到多线程插入数据
[b]问题补充:[/b]
谢谢两位的回答,还有几个疑问
to ranLoD: "一个标识对象,当入库的线程读取到标识对象的时候线程结束" 一个标识对象是什么意思,怎么样读取标识对象,能否写出几句简单的代码
to pwg17:"读取的线程读一批URL出来后,更新这批URL",怎么样做到呢,怎么控制数量,怎么更新呢,能否写出几句简单的代码
[b]问题补充:[/b]
因为还有程序不断往数据库里插入新数据,一开始读完十万可以,但还是有一个线程定时扫描数据吧?
[b]问题补充:[/b]
谢谢pwg17的一直回答。是的,是写一个爬虫。因为分析抓取时,是用别的语言写的,不保存在数据库里没法进行交互啊
[b]问题补充:[/b]
是的,我只是负责下载页面,其他分析不是我管。这几天看别人用C#写一个多线程抓取,感觉运行起来比Java快,C#有个HttpWebRequest组件封装挺好的,感觉比java的好用,不知是否理解正确。我也打算用hibernate试试,不知道多线程下hibernate有没有要注意的问题。分有点少,我是新人,多多理解啊。也谢谢各位的回答。
嗯,我就是用C#的,HttpWebRequest是挺方便的。没有哪个语言写就快,看些代码的人而已。想快速的话,程序用多线程,然后再弄成分布式。感觉你们蜘蛛这里拆分成不同部分不同人负责,想快速的话,只能是看整体实现的怎样了。hibernate不是很熟悉,在蜘蛛这里用不是很适合,个人感觉,或者用Ibatis吧。
如果这个任务由我来做的话,
我会建两个ArrayBlockingQueue,一个用来存url,
一个用来存抓完的url+结果+..你要的东西。
在建立一个独立的线程从结果的Queue不断拿数据填入数据库,这样就不是并发的访问数据库了,一个标识对象,当入库的线程读取到标识对象的时候线程结束
很简单的一个需求。
出现上面的异常,是你频繁链接数据库,数据库链接耗尽了吧,请检查代码,和用连接池。
按照你现有的解决思路的话,可用 队列+多线程 的模式。一边读一边更新可改为:读取的线程读一批URL出来后,更新这批URL,然后才放进队列供后面的线程读取。
其实一次性读取10W URL出来也没什么,占用内存也不多,一次性读取,比起频繁操作数据库,花费这点内存还是值得的。
sql语句控制,select top 一定数目isReaded符合要求的数据出来,然后update这批数据isReaded标志。建议用update ...... where id in(1,2,3,...)。
10W其实不多,不知道你具体情况,我的话会选择一次性读取出来吧,简单,一个周期只读取一次数据库。
那用[quote]
sql语句控制,select top 一定数目isReaded符合要求的数据出来,然后update这批数据isReaded标志。建议用update ...... where id in(1,2,3,...)。
[/quote]
这个方案咯。
是写爬虫吗?数据库保存中间分析出来的URL不是好主意。
为什么是别的语言?别人提供的分析接口?不是你负责?
你只是负责下载页面回来?
通过数据库交互的话,那就用上面的方案吧。
看你程序报的错误,代码应该还存在很多问题。
可用队列+多线程的方式。还有注意共享的资源是否线程安全。线程也并不是越多越好。