我曾经想过尝试编写一个简单的爬虫,可能会爬行并为我们的NPO网站和内容生成一份调查结果列表.
有没有人对如何做到这一点有任何想法?你在哪里指出爬虫开始?它如何发送回调查结果并继续爬行?它是如何知道它发现的等等.
你肯定会重新发明轮子.但这是基础知识:
未访问的URL列表 - 将其与一个或多个起始页面一起播种
访问过的网址列表 - 因此您不会在圈子中四处走动
您不感兴趣的URL的一组规则 - 因此您不会索引整个Internet
将它们放在持久存储中,这样您就可以停止并启动爬虫而不会丢失状态.
算法是:
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 } } }
爬虫的复杂部分是,如果您想将其扩展到大量的网站/请求.在这种情况下,您将不得不处理以下问题:
不可能将信息全部保存在一个数据库中.
没有足够的RAM来处理巨大的索引
多线程性能和并发性
爬虫陷阱(通过更改网址,日历,会话ID ...创建的无限循环)和重复的内容.
从多台计算机上爬行
格式错误的HTML代码
服务器的常量http错误
没有压缩的数据库,使您对空间的需求大约增加8倍.
重新抓取例程和优先级.
使用压缩请求(Deflate/gzip)(适用于任何类型的爬虫).
还有一些重要的事情
尊重robots.txt
并且每个请求上的爬虫延迟都不会使Web服务器窒息.
多线程Web爬虫
如果您想要抓取大型网站,那么您应该编写一个多线程抓取工具.连接,获取和写入文件/数据库中的爬行信息 - 这些是爬行的三个步骤,但如果使用单个线程而不是CPU,则网络利用率将会下降.
多线程Web爬网程序需要两个数据结构 - linksVisited(这应该实现为hashmap或trai)和linksToBeVisited(这是一个队列).
Web爬网程序使用BFS遍历万维网.
基本网络爬虫的算法: -
将一个或多个种子URL添加到linksToBeVisited.必须同步向linksToBeVisited添加URL的方法.
从linksToBeVisited弹出一个元素并将其添加到linksVisited.必须同步这个来自linksToBeVisited的弹出网址的pop方法.
从互联网上获取页面.
解析文件并将页面中找到的任何到目前为止未访问的链接添加到linksToBeVisited.如果需要,可以过滤URL.用户可以提供一组规则来过滤要扫描的URL.
页面上找到的必要信息保存在数据库或文件中.
重复步骤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; } }
爬虫的概念很简单。
您可以通过HTTP GET获取根页,对其进行解析以查找URL并将它们放在队列中,除非已对其进行了解析(因此,您需要全局记录已解析的页面)。
您可以使用Content-type标头来找出内容的类型,并将搜寻器限制为仅解析HTML类型。
您可以剥离HTML标记以获取纯文本,然后可以对纯文本进行文本分析(以获取标记等页面的内容)。如果您已经高级的话,甚至可以在图片的alt / title标签上执行此操作。
在后台,您可以拥有一个线程池,这些线程从Queue中获取URL并执行相同的操作。您当然要限制线程数。
如果您的NPO网站相对较大或较为复杂(动态页面有效地创建'黑洞',就像带有'次日'链接的日历一样),您最好使用真正的网络爬虫,如Heritrix.
如果这些网站总共只有几页,你只需使用curl或wget或你自己就可以获得.只要记住,如果它们开始变大,或者你开始使你的脚本更复杂,只需使用真正的爬虫或至少查看它的来源,看看它们在做什么以及为什么.
一些问题(还有更多):
黑洞(如上所述)
重试(如果你得到500怎么办?)
重定向
流量控制(否则你可能成为网站的负担)
robots.txt实现