61 web-crawler
我曾经想过尝试编写一个简单的爬虫,可能会爬行并为我们的NPO网站和内容生成一份调查结果列表.
有没有人对如何做到这一点有任何想法?你在哪里指出爬虫开始?它如何发送回调查结果并继续爬行?它是如何知道它发现的等等.
sli*_*lim 147
你肯定会重新发明轮子.但这是基础知识:
将它们放在持久存储中,这样您就可以停止并启动爬虫而不会丢失状态.
算法是:
while(list of unvisited URLs is not empty) {
take URL from list
remove it from the unvisited list and add it to the visited list
fetch content
record whatever it is you want to about the content
if content is HTML {
parse out URLs from links
foreach URL {
if it matches your rules
and it's not already in either the visited or unvisited list
add it to the unvisited list
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 30
爬虫的复杂部分是,如果您想将其扩展到大量的网站/请求.在这种情况下,您将不得不处理以下问题:
不可能将信息全部保存在一个数据库中.
没有足够的RAM来处理巨大的索引
多线程性能和并发性
爬虫陷阱(通过更改网址,日历,会话ID ...创建的无限循环)和重复的内容.
从多台计算机上爬行
格式错误的HTML代码
服务器的常量http错误
没有压缩的数据库,使您对空间的需求大约增加8倍.
重新抓取例程和优先级.
使用压缩请求(Deflate/gzip)(适用于任何类型的爬虫).
还有一些重要的事情
尊重robots.txt
并且每个请求上的爬虫延迟都不会使Web服务器窒息.
多线程Web爬虫
如果您想要抓取大型网站,那么您应该编写一个多线程抓取工具.连接,获取和写入文件/数据库中的爬行信息 - 这些是爬行的三个步骤,但如果使用单个线程而不是CPU,则网络利用率将会下降.
多线程Web爬网程序需要两个数据结构 - linksVisited(这应该实现为hashmap或trai)和linksToBeVisited(这是一个队列).
Web爬网程序使用BFS遍历万维网.
基本网络爬虫的算法: -
重复步骤2到5,直到队列为linksToBeVisited为空.
这是一个关于如何同步线程的代码片段....
public void add(String site) {
synchronized (this) {
if (!linksVisited.contains(site)) {
linksToBeVisited.add(site);
}
}
}
public String next() {
if (linksToBeVisited.size() == 0) {
return null;
}
synchronized (this) {
// Need to check again if size has changed
if (linksToBeVisited.size() > 0) {
String s = linksToBeVisited.get(0);
linksToBeVisited.remove(0);
linksVisited.add(s);
return s;
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)爬虫的概念很简单。
您可以通过HTTP GET获取根页,对其进行解析以查找URL并将它们放在队列中,除非已对其进行了解析(因此,您需要全局记录已解析的页面)。
您可以使用Content-type标头来找出内容的类型,并将搜寻器限制为仅解析HTML类型。
您可以剥离HTML标记以获取纯文本,然后可以对纯文本进行文本分析(以获取标记等页面的内容)。如果您已经高级的话,甚至可以在图片的alt / title标签上执行此操作。
在后台,您可以拥有一个线程池,这些线程从Queue中获取URL并执行相同的操作。您当然要限制线程数。
使用 wget,进行递归网络吸盘,这会将所有文件转储到硬盘上,然后编写另一个脚本来遍历所有下载的文件并分析它们。
编辑:或者也许用curl代替wget,但我不熟悉curl,我不知道它是否像wget一样进行递归下载。