
htmlunit抓取动态网页
htmlunit抓取动态网页(中小微公司网络爬虫技术总结及解决办法(一))
网站优化 • 优采云 发表了文章 • 0 个评论 • 85 次浏览 • 2022-02-01 04:27
网络爬虫技术总结
对于大数据行业来说,数据的价值不言而喻。在这个信息爆炸的时代,互联网上的信息数据太多了。对于中小微企业来说,合理使用爬虫爬取有价值的数据,是为了弥补自身先天的数据短缺。板子的最佳选择,本文主要从爬虫原理、架构、分类和反爬虫技术方面总结了爬虫技术。
1、爬虫技术概述
网络爬虫是一种程序或脚本,它根据一定的规则自动爬取万维网上的信息。它们广泛应用于互联网搜索引擎或其他类似的网站,并且可以自动采集所有它可以访问的页面的内容来获取或更新这些网站的内容和检索方式. 从功能上来说,爬虫一般分为数据采集、处理、存储三部分。
传统爬虫从一个或多个初始网页的URL开始,获取初始网页上的URL。在对网页进行爬取的过程中,不断地从当前页面中提取新的 URL 并放入队列中,直到满足系统的某些停止条件。焦点爬虫的工作流程比较复杂。它需要按照一定的网页分析算法过滤掉与主题无关的链接,保留有用的链接,并放入等待抓取的URL队列中。然后,它会根据一定的搜索策略从队列中选择下一个要爬取的网页URL,并重复上述过程,直到达到系统的一定条件并停止。另外,爬虫爬取的所有网页都会被系统存储,进行一定的分析、过滤和索引,以供后续查询和检索;对于重点爬虫来说,这个过程中得到的分析结果也可能对后续的爬取过程给出反馈和指导。
与通用网络爬虫相比,聚焦爬虫还需要解决三个主要问题:
(1)爬取目标的描述或定义;
(2)网页或数据的分析和过滤;
(3)URL 的搜索策略。
2、爬虫原理
2.1网络爬虫原理
网络爬虫系统的功能是下载网页数据,为搜索引擎系统提供数据源。许多大型网络搜索引擎系统被称为基于Web数据的搜索引擎系统采集,如Google、百度等。这显示了网络爬虫系统在搜索引擎中的重要性。除了供用户阅读的文字信息外,网页还收录一些超链接信息。网络爬虫系统通过网页中的超链接信息不断获取网络上的其他网页。正是因为这个采集进程像爬虫或者蜘蛛一样在网络上漫游,所以才叫做网络爬虫系统或者网络蜘蛛系统,英文叫Spider或者Crawler。
2.2网络爬虫系统的工作原理
在网络爬虫的系统框架中,主要流程由控制器、解析器和资源库三部分组成。控制器的主要工作是为多个线程中的每个爬虫线程分配工作任务。解析器的主要工作是下载网页和处理页面,主要是处理一些JS脚本标签、CSS代码内容、空格字符、HTML标签等。爬虫的基本工作是由解析器完成的。资源库用于存储下载的网络资源。通常使用大型数据库,例如 Oracle 数据库来存储和索引它。
控制器
控制器是网络爬虫的中央控制器。主要负责根据系统发送的URL链接分配一个线程,然后启动线程调用爬虫爬取网页。
解析器
解析器负责网络爬虫的主要部分。它的主要任务是:下载网页的功能,处理网页的文本,如过滤,提取特殊的HTML标签,分析数据。
资源库
它主要是一个容器,用于存储从网页下载的数据记录,并为索引生成提供目标源。大中型数据库产品包括:Oracle、SqlServer等。
网络爬虫系统一般会选择一些比较重要的出度(网页中超链接数)网站较大的URL作为种子URL集。网络爬虫系统使用这些种子集作为初始 URL 来开始数据爬取。因为网页中收录链接信息,所以会通过已有网页的URL获取一些新的URL。网页之间的指向结构可以看作是一片森林。每个种子 URL 对应的网页是森林中一棵树的根节点。.
这样,网络爬虫系统就可以按照广度优先算法或深度优先算法遍历所有网页。由于深度优先搜索算法可能导致爬虫系统陷入网站内部,不利于搜索距离网站首页比较近的网页信息,因此广度优先搜索算法一般使用采集网页。网络爬虫系统首先将种子 URL 放入下载队列,然后简单地从队列头部获取一个 URL 来下载其对应的网页。获取网页内容并存储后,通过解析网页中的链接信息可以得到一些新的URL,并将这些URL加入到下载队列中。然后取出一个网址,下载其对应的网页,
网络爬虫的基本工作流程如下:
1.首先选择一个精心挑选的种子 URL 的子集;
2.将这些网址放入待抓取的网址队列中;
3. 从待爬取URL队列中取出待爬取的URL,解析DNS,获取主机IP,下载该URL对应的网页,存入下载的网页库中。此外,将这些 URL 放入 Crawl URLs 队列;
4.解析URL队列中已经爬取的URL,分析其中的其他URL,将URL放入待爬取的URL队列,从而进入下一个循环。
2.3 爬取策略
在爬虫系统中,待爬取的 URL 队列是一个重要的部分。待爬取的URL队列中的URL的排列顺序也是一个重要的问题,因为它涉及到先爬到哪个页面,再爬到哪个页面。确定这些 URL 排列顺序的方法称为爬取策略。下面重点介绍几种常见的爬取策略:
2.3.1 深度优先遍历策略
深度优先遍历策略是指网络爬虫会从起始页开始,一个接一个的链接,处理完该行再到下一个起始页,继续跟踪该链接。我们以下图为例:
遍历路径:AF-GE-H-IBCD
2.3.2 广度优先遍历策略
广度优先遍历的基本思想是将新下载的网页中找到的链接直接插入待爬取URL队列的末尾。也就是说,网络爬虫会先爬取起始网页链接的所有网页,然后选择其中一个链接的网页,继续爬取该网页链接的所有网页。或者以上图为例:
遍历路径:ABCDE-FGHI
2.3.3 反向链接策略
反向链接数是指从其他网页指向一个网页的链接数。反向链接的数量表示网页内容被他人推荐的程度。因此,在很多情况下,搜索引擎的爬取系统会使用这个指标来评估网页的重要性,从而确定不同网页的爬取顺序。
在真实的网络环境中,由于广告链接和作弊链接的存在,反向链接的数量并不能完全等同于他人的重要性。因此,搜索引擎倾向于考虑一些可靠的反向链接计数。
2.3.4PartialPageRank 策略
PartialPageRank算法借鉴了PageRank算法的思想:对于下载的网页,连同待爬取的URL队列中的URL,形成一组网页,计算每个页面的PageRank值。计算完成后,计算待爬取的URL队列中的URL。按 PageRank 值排序并按该顺序抓取页面。
如果每次爬取一个页面都重新计算一次PageRank值,一个折中的方案是每次爬取K个页面都重新计算一次PageRank值。但是这种情况还是有一个问题:对于下载页面中分析的链接,也就是我们前面提到的那部分未知网页,暂时没有PageRank值。为了解决这个问题,给这些页面一个临时的PageRank值:把这个网页的所有传入链接传入的PageRank值聚合起来,从而形成未知页面的PageRank值,从而参与排序.
2.3.5OPICStrategy
该算法实际上为页面分配了一个重要性分数。在算法开始之前,所有页面都会获得相同的初始现金。当某个页面P被下载时,P的现金分配给从P分析的所有链接,P的现金被清空。根据现金数量对待爬取URL队列中的所有页面进行排序。
2.3.六大网站优先策略
所有待爬取的URL队列中的网页都按照它们所属的网站进行分类。网站需要下载的页面较多,请先下载。这种策略也称为大站点优先策略。
3、爬虫分类
我应该选择 Nutch、Crawler4j、WebMagic、scrapy、WebCollector 还是其他来开发网络爬虫?上面提到的爬虫类,基本上可以分为三类:
(1)分布式爬虫:Nutch
(2)JAVA 爬虫:Crawler4j、WebMagic、WebCollector
(3)非JAVA爬虫:scrapy(基于Python语言开发)
3.1 分布式爬虫
爬虫使用分布式,主要解决两个问题:
1)海量网址管理
2)网速
现在比较流行的分布式爬虫是Apache的Nutch。但是对于大多数用户来说,Nutch 是这些爬虫中最差的选择,原因如下:
1)Nutch 是为搜索引擎设计的爬虫。大多数用户需要一个爬虫来进行准确的数据爬取(精细提取)。Nutch 运行的三分之二的流程是为搜索引擎设计的。提取意义不大。换句话说,使用 Nutch 进行数据提取会在不必要的计算上浪费大量时间。而如果你试图通过Nutch的二次开发使其适合提取业务,你基本上会破坏Nutch的框架,将Nutch改得面目全非,并且有能力修改Nutch,还不如自己写一个新的. 分布式爬虫框架。
2)Nutch 依赖hadoop 运行,hadoop 本身消耗大量时间。如果集群机器数量少,爬取速度不如单机爬虫快。
3)虽然Nutch有一套插件机制,但还是作为亮点来宣传的。可以看到一些开源的Nutch插件,提供精准提取功能。但是任何开发过 Nutch 插件的人都知道 Nutch 的插件系统有多糟糕。使用反射机制加载和调用插件,使得程序的编写和调试变得异常困难,更不用说在其上开发复杂的提取系统了。并且 Nutch 没有提供对应的插件挂载点进行精细提取。Nutch的插件只有五六个挂载点,而这五六个挂载点都是给搜索引擎服务的,不提供细提取的挂载点。Nutch 的大部分精炼提取插件都挂载在“页面解析”(parser)挂载点上。这个挂载点其实是用来解析链接(为后续爬取提供URL)和提供一些搜索引擎的。易于提取的网页信息(元信息、网页文本)。
4)使用Nutch进行爬虫的二次开发,编写和调试爬虫所需的时间往往是单机爬虫所需时间的十倍以上。学习 Nutch 源码的成本非常高,更何况团队中的每个人都必须了解 Nutch 源码。在调试过程中,会出现程序本身以外的各种问题(hadoop问题、hbase问题)。
5)很多人说Nutch2有gora,可以将数据持久化到avro文件、hbase、mysql等,其实很多人都误解了。这里所说的持久化数据是指在avro、hbase、mysql中存储URL信息(URL管理所需的数据)。不是您要提取的结构化数据。事实上,对于大多数人来说,URL 信息存在于何处并不重要。
6)Nutch2 的版本目前不适合开发。Nutch的官方稳定版是nutch2.2.1,但是这个版本绑定了gora-0.3。如果要使用hbase和nutch(大多数人使用nutch2是为了使用hbase),只能使用版本0.90左右的hbase,相应地,将hadoop版本降低到hadoop0.左右@>2。而且nutch2的官方教程也颇具误导性。Nutch2的教程有两个,分别是Nutch1.x和Nutch2.x。Nutch2.x官网是为了支持hbase0.94而写的。但其实这个Nutch2.x是指Nutch2.3之前和Nutch2.2.1之后的一个版本,在官方SVN中不断更新。而且它'
所以,如果你不是搜索引擎,尽量不要选择 Nutch 作为爬虫。一些团队喜欢跟风。他们坚持选择Nutch来开发精制履带。事实上,这是针对Nutch的声誉。当然,最终的结果往往是项目延期。
如果你在做搜索引擎,Nutch1.x 是一个非常不错的选择。Nutch1.x 和 solr 或 es 可以组成一个非常强大的搜索引擎。如果必须使用 Nutch2,建议等到 Nutch2.3 发布。当前的 Nutch2 是一个非常不稳定的版本。
分布式爬虫平台架构图
3.2JAVA爬虫
在这里,将JAVA爬虫划分为一个单独的类别,因为JAVA在网络爬虫的生态系统中非常完善。相关资料也是最全的。这里可能有争议,我只是随便说说。
其实开源网络爬虫(框架)的开发非常简单,前人已经解决了困难和复杂的问题(如DOM树解析定位、字符集检测、海量URL去重等),可以据说没有技术含量。. 包括Nutch,其实Nutch的技术难点就是开发hadoop,代码本身也很简单。从某种意义上说,网络爬虫类似于遍历本机的文件以查找文件中的信息。没有任何困难。选择开源爬虫框架的原因是为了省事。比如爬虫的URL管理、线程池等模块,任何人都可以做,但是需要一段时间的调试和修改才能稳定下来。
对于爬虫的功能。用户比较关心的问题往往是:
1)爬虫是否支持多线程,爬虫可以使用代理,爬虫可以抓取重复数据,爬虫可以抓取JS生成的信息吗?
不支持多线程、不支持代理、不能过滤重复URL的不叫开源爬虫,叫循环执行http请求。
js生成的信息能否被爬取与爬虫本身关系不大。爬虫主要负责遍历网站和下载页面。爬取js产生的信息与网页信息提取模块有关,往往需要模拟浏览器(htmlunit、selenium)来完成。这些模拟浏览器通常需要花费大量时间来处理一个页面。因此,一种策略是利用这些爬虫遍历网站,当遇到需要解析的页面时,将网页的相关信息提交给模拟浏览器,完成对JS生成信息的提取。
2)爬虫可以抓取ajax信息吗?
网页上有一些异步加载的数据。爬取数据有两种方式:使用模拟浏览器(问题1中描述),或者分析ajax的http请求,自己生成ajax请求的url,获取返回的数据。如果你自己生成ajax请求,那么使用开源爬虫有什么意义呢?其实就是利用开源爬虫的线程池和URL管理功能(比如断点爬取)。
如果我已经可以生成我需要的ajax请求(列表),我该如何使用这些爬虫来爬取这些请求呢?
爬虫往往被设计成广度遍历或深度遍历的方式来遍历静态或动态页面。爬取ajax信息属于deepweb(深网)的范畴,虽然大部分爬虫并不直接支持。但它也可以通过某些方式完成。例如,WebCollector 使用广度遍历来遍历 网站。爬虫的第一轮爬取就是爬取种子集(seeds)中的所有url。简单来说就是将生成的ajax请求作为种子,放入爬虫中。使用爬虫对这些种子进行深度为 1 的广度遍历(默认为广度遍历)。
3)爬虫如何爬取待登录的网站?
这些开源爬虫都支持在爬取时指定cookies,而模拟登录主要依赖cookies。至于如何获取cookies,就不是爬虫管理的问题了。您可以手动获取cookies,使用http请求模拟登录,或者使用模拟浏览器自动登录。
4)爬虫如何从网页中提取信息?
开源爬虫一般会集成网页提取工具。主要支持两种规范:CSSSELECTOR 和 XPATH。至于哪个更好,我这里就不评论了。
5)爬虫是如何保存网页信息的?
有一些爬虫带有一个负责持久性的模块。例如,webmagic 有一个名为 pipeline 的模块。通过简单的配置,爬虫提取的信息可以持久化到文件、数据库等。还有一些爬虫不直接为用户提供数据持久化模块。比如 crawler4j 和 webcollector。让用户在网页处理模块中添加提交数据库的操作。至于用管道模块好不好,就类似于用ORM操作数据库好不好的问题,看你的业务。
6)爬虫被网站拦截了怎么办?
爬虫被网站阻塞,可以通过使用多个代理(随机代理)来解决。但是这些开源爬虫一般不直接支持随机代理的切换。因此,用户经常需要将获取到的agent放入一个全局数组中,并编写一段代码让agent随机获取(从数组中)。
7)网页可以调用爬虫吗?
爬虫的调用是在Web的服务器端调用的。您可以按照平时使用的方式使用它。可以使用这些爬虫。
8)爬虫速度怎么样?
单机开源爬虫的速度基本可以用到本地网速的极限。爬虫速度慢往往是因为用户减少了线程数,网速慢,或者数据持久化时与数据库的交互慢。而这些东西往往是由用户的机器和二次开发的代码决定的。这些开源爬虫的速度非常好。
9) 明明代码写对了,但是数据爬不出来。爬虫有问题吗?不同的爬虫可以解决吗?
如果代码写得正确,无法爬取数据,其他爬虫也将无法爬取。在这种情况下,要么是 网站 阻止了您,要么您抓取的数据是由 javascript 生成的。如果无法爬取数据,则无法通过更改爬虫来解决。
10)哪个爬虫可以判断网站是否已经爬完,哪个爬虫可以根据主题爬取?
爬虫无法判断网站是否已经爬完,只能尽量覆盖。
至于根据主题爬,爬虫把内容爬下来后就知道主题是什么了。因此,通常是整体爬下来,然后对内容进行过滤。如果爬取的范围太广,可以通过限制 URL 正则化来缩小范围。
11)哪个爬虫的设计模式和架构比较好?
设计模式是胡说八道。都说软件设计模式不错,软件开发后总结了几种设计模式。设计模式对软件开发没有指导意义。使用设计模式设计爬虫只会让爬虫的设计更加臃肿。
至于架构,目前开源爬虫主要是设计详细的数据结构,比如爬取线程池、任务队列等,大家都可以控制。爬虫的业务太简单了,用任何框架都谈不上。
所以对于 JAVA 开源爬虫,我认为,只要找到一个运行良好的。如果业务复杂,使用哪个爬虫,只能通过复杂的二次开发来满足需求。
3.3 非JAVA爬虫
在非JAVA语言编写的爬虫中,不乏优秀的爬虫。这里提取为一个类别,不是为了讨论爬虫本身的好坏,而是为了讨论larbin、scrapy等爬虫对开发成本的影响。
先说python爬虫,python用30行代码就可以完成JAVA50行代码的任务。Python写代码确实很快,但是在调试代码阶段,调试python代码所消耗的时间往往比编码阶段节省的时间要多得多。使用python开发,为了保证程序的正确性和稳定性,需要编写更多的测试模块。当然,如果爬取规模不大,爬取业务也不复杂,用scrapy还是不错的,可以轻松完成爬取任务。
上图是Scrapy的架构图。绿线是数据流。从初始 URL 开始,Scheduler 会将其交给 Downloader 进行下载。下载完成后交给Spider进行分析,将要保存的数据发送到ItemPipeline。那就是对数据进行后处理。此外,可以在数据流通道中安装各种中间件,进行必要的处理。因此,在开发爬虫时,最好先规划好各个模块。我的做法是分别规划下载模块、爬取模块、调度模块、数据存储模块。
对于C++爬虫来说,学习成本会比较大。而且不能只计算一个人的学习成本。如果软件需要一个团队来开发或者移交,那就是很多人的学习成本。软件调试不是那么容易。
还有一些ruby和php爬虫,这里就不多评价了。确实有一些非常小的data采集任务,在ruby或者php中都用得上。但是,要选择这些语言的开源爬虫,一方面需要调查相关的生态系统,另一方面,这些开源爬虫可能存在一些你找不到的bug(很少有人使用它们,而且信息也较少)
4、反爬虫技术
由于搜索引擎的普及,网络爬虫已经成为一种非常流行的网络技术。除了专注于搜索的谷歌、雅虎、微软和百度之外,几乎每个大型门户网站网站都有自己的搜索引擎,大大小小的。可以叫的名字有几十种,不知道的种类有上万种。对于一个内容驱动的网站,难免会被网络爬虫光顾。
一些智能搜索引擎爬虫的爬取频率比较合理,资源消耗也比较小,但是很多不良网络爬虫对网页的爬取能力很差,经常循环重复上百个请求。拿,这种爬虫对中小型网站来说往往是毁灭性的打击,尤其是一些缺乏爬虫编写经验的程序员编写的爬虫,破坏性极大,导致网站访问压力会很大非常大,这将导致 网站 访问缓慢甚至无法访问。
一般网站反爬虫从三个方面进行:用户请求的头文件、用户行为、网站目录和数据加载方式。前两种比较容易遇到,从这些角度来看,大部分网站都是反爬虫。会使用第三种使用ajax的网站,增加了爬取的难度。
4.1 反爬虫通过Headers
反爬取用户请求的头部是最常见的反爬取策略。很多网站会检测header的User-Agent,有的网站会检测Referer(有些资源的防盗链网站就是检测Referer)。如果遇到这样的反爬虫机制,可以直接在爬虫中添加Headers,将浏览器的User-Agent复制到爬虫的Headers中;或者将Referer值改为目标网站域名。对于检测Headers的反爬虫,在爬虫中修改或添加Headers可以很好的绕过。
[评论:它通常很容易被忽略。通过对请求的抓包分析,确定referer,并添加到程序中模拟访问请求的header]
4.2 基于用户行为的反爬虫
网站的另一部分是检测用户行为,比如同一个IP在短时间内多次访问同一个页面,或者同一个账号在短时间内多次执行相同的操作。 查看全部
htmlunit抓取动态网页(中小微公司网络爬虫技术总结及解决办法(一))
网络爬虫技术总结
对于大数据行业来说,数据的价值不言而喻。在这个信息爆炸的时代,互联网上的信息数据太多了。对于中小微企业来说,合理使用爬虫爬取有价值的数据,是为了弥补自身先天的数据短缺。板子的最佳选择,本文主要从爬虫原理、架构、分类和反爬虫技术方面总结了爬虫技术。
1、爬虫技术概述
网络爬虫是一种程序或脚本,它根据一定的规则自动爬取万维网上的信息。它们广泛应用于互联网搜索引擎或其他类似的网站,并且可以自动采集所有它可以访问的页面的内容来获取或更新这些网站的内容和检索方式. 从功能上来说,爬虫一般分为数据采集、处理、存储三部分。
传统爬虫从一个或多个初始网页的URL开始,获取初始网页上的URL。在对网页进行爬取的过程中,不断地从当前页面中提取新的 URL 并放入队列中,直到满足系统的某些停止条件。焦点爬虫的工作流程比较复杂。它需要按照一定的网页分析算法过滤掉与主题无关的链接,保留有用的链接,并放入等待抓取的URL队列中。然后,它会根据一定的搜索策略从队列中选择下一个要爬取的网页URL,并重复上述过程,直到达到系统的一定条件并停止。另外,爬虫爬取的所有网页都会被系统存储,进行一定的分析、过滤和索引,以供后续查询和检索;对于重点爬虫来说,这个过程中得到的分析结果也可能对后续的爬取过程给出反馈和指导。
与通用网络爬虫相比,聚焦爬虫还需要解决三个主要问题:
(1)爬取目标的描述或定义;
(2)网页或数据的分析和过滤;
(3)URL 的搜索策略。
2、爬虫原理
2.1网络爬虫原理
网络爬虫系统的功能是下载网页数据,为搜索引擎系统提供数据源。许多大型网络搜索引擎系统被称为基于Web数据的搜索引擎系统采集,如Google、百度等。这显示了网络爬虫系统在搜索引擎中的重要性。除了供用户阅读的文字信息外,网页还收录一些超链接信息。网络爬虫系统通过网页中的超链接信息不断获取网络上的其他网页。正是因为这个采集进程像爬虫或者蜘蛛一样在网络上漫游,所以才叫做网络爬虫系统或者网络蜘蛛系统,英文叫Spider或者Crawler。
2.2网络爬虫系统的工作原理
在网络爬虫的系统框架中,主要流程由控制器、解析器和资源库三部分组成。控制器的主要工作是为多个线程中的每个爬虫线程分配工作任务。解析器的主要工作是下载网页和处理页面,主要是处理一些JS脚本标签、CSS代码内容、空格字符、HTML标签等。爬虫的基本工作是由解析器完成的。资源库用于存储下载的网络资源。通常使用大型数据库,例如 Oracle 数据库来存储和索引它。
控制器
控制器是网络爬虫的中央控制器。主要负责根据系统发送的URL链接分配一个线程,然后启动线程调用爬虫爬取网页。
解析器
解析器负责网络爬虫的主要部分。它的主要任务是:下载网页的功能,处理网页的文本,如过滤,提取特殊的HTML标签,分析数据。
资源库
它主要是一个容器,用于存储从网页下载的数据记录,并为索引生成提供目标源。大中型数据库产品包括:Oracle、SqlServer等。
网络爬虫系统一般会选择一些比较重要的出度(网页中超链接数)网站较大的URL作为种子URL集。网络爬虫系统使用这些种子集作为初始 URL 来开始数据爬取。因为网页中收录链接信息,所以会通过已有网页的URL获取一些新的URL。网页之间的指向结构可以看作是一片森林。每个种子 URL 对应的网页是森林中一棵树的根节点。.
这样,网络爬虫系统就可以按照广度优先算法或深度优先算法遍历所有网页。由于深度优先搜索算法可能导致爬虫系统陷入网站内部,不利于搜索距离网站首页比较近的网页信息,因此广度优先搜索算法一般使用采集网页。网络爬虫系统首先将种子 URL 放入下载队列,然后简单地从队列头部获取一个 URL 来下载其对应的网页。获取网页内容并存储后,通过解析网页中的链接信息可以得到一些新的URL,并将这些URL加入到下载队列中。然后取出一个网址,下载其对应的网页,
网络爬虫的基本工作流程如下:
1.首先选择一个精心挑选的种子 URL 的子集;
2.将这些网址放入待抓取的网址队列中;
3. 从待爬取URL队列中取出待爬取的URL,解析DNS,获取主机IP,下载该URL对应的网页,存入下载的网页库中。此外,将这些 URL 放入 Crawl URLs 队列;
4.解析URL队列中已经爬取的URL,分析其中的其他URL,将URL放入待爬取的URL队列,从而进入下一个循环。
2.3 爬取策略
在爬虫系统中,待爬取的 URL 队列是一个重要的部分。待爬取的URL队列中的URL的排列顺序也是一个重要的问题,因为它涉及到先爬到哪个页面,再爬到哪个页面。确定这些 URL 排列顺序的方法称为爬取策略。下面重点介绍几种常见的爬取策略:
2.3.1 深度优先遍历策略
深度优先遍历策略是指网络爬虫会从起始页开始,一个接一个的链接,处理完该行再到下一个起始页,继续跟踪该链接。我们以下图为例:
遍历路径:AF-GE-H-IBCD
2.3.2 广度优先遍历策略
广度优先遍历的基本思想是将新下载的网页中找到的链接直接插入待爬取URL队列的末尾。也就是说,网络爬虫会先爬取起始网页链接的所有网页,然后选择其中一个链接的网页,继续爬取该网页链接的所有网页。或者以上图为例:
遍历路径:ABCDE-FGHI
2.3.3 反向链接策略
反向链接数是指从其他网页指向一个网页的链接数。反向链接的数量表示网页内容被他人推荐的程度。因此,在很多情况下,搜索引擎的爬取系统会使用这个指标来评估网页的重要性,从而确定不同网页的爬取顺序。
在真实的网络环境中,由于广告链接和作弊链接的存在,反向链接的数量并不能完全等同于他人的重要性。因此,搜索引擎倾向于考虑一些可靠的反向链接计数。
2.3.4PartialPageRank 策略
PartialPageRank算法借鉴了PageRank算法的思想:对于下载的网页,连同待爬取的URL队列中的URL,形成一组网页,计算每个页面的PageRank值。计算完成后,计算待爬取的URL队列中的URL。按 PageRank 值排序并按该顺序抓取页面。
如果每次爬取一个页面都重新计算一次PageRank值,一个折中的方案是每次爬取K个页面都重新计算一次PageRank值。但是这种情况还是有一个问题:对于下载页面中分析的链接,也就是我们前面提到的那部分未知网页,暂时没有PageRank值。为了解决这个问题,给这些页面一个临时的PageRank值:把这个网页的所有传入链接传入的PageRank值聚合起来,从而形成未知页面的PageRank值,从而参与排序.
2.3.5OPICStrategy
该算法实际上为页面分配了一个重要性分数。在算法开始之前,所有页面都会获得相同的初始现金。当某个页面P被下载时,P的现金分配给从P分析的所有链接,P的现金被清空。根据现金数量对待爬取URL队列中的所有页面进行排序。
2.3.六大网站优先策略
所有待爬取的URL队列中的网页都按照它们所属的网站进行分类。网站需要下载的页面较多,请先下载。这种策略也称为大站点优先策略。
3、爬虫分类
我应该选择 Nutch、Crawler4j、WebMagic、scrapy、WebCollector 还是其他来开发网络爬虫?上面提到的爬虫类,基本上可以分为三类:
(1)分布式爬虫:Nutch
(2)JAVA 爬虫:Crawler4j、WebMagic、WebCollector
(3)非JAVA爬虫:scrapy(基于Python语言开发)
3.1 分布式爬虫
爬虫使用分布式,主要解决两个问题:
1)海量网址管理
2)网速
现在比较流行的分布式爬虫是Apache的Nutch。但是对于大多数用户来说,Nutch 是这些爬虫中最差的选择,原因如下:
1)Nutch 是为搜索引擎设计的爬虫。大多数用户需要一个爬虫来进行准确的数据爬取(精细提取)。Nutch 运行的三分之二的流程是为搜索引擎设计的。提取意义不大。换句话说,使用 Nutch 进行数据提取会在不必要的计算上浪费大量时间。而如果你试图通过Nutch的二次开发使其适合提取业务,你基本上会破坏Nutch的框架,将Nutch改得面目全非,并且有能力修改Nutch,还不如自己写一个新的. 分布式爬虫框架。
2)Nutch 依赖hadoop 运行,hadoop 本身消耗大量时间。如果集群机器数量少,爬取速度不如单机爬虫快。
3)虽然Nutch有一套插件机制,但还是作为亮点来宣传的。可以看到一些开源的Nutch插件,提供精准提取功能。但是任何开发过 Nutch 插件的人都知道 Nutch 的插件系统有多糟糕。使用反射机制加载和调用插件,使得程序的编写和调试变得异常困难,更不用说在其上开发复杂的提取系统了。并且 Nutch 没有提供对应的插件挂载点进行精细提取。Nutch的插件只有五六个挂载点,而这五六个挂载点都是给搜索引擎服务的,不提供细提取的挂载点。Nutch 的大部分精炼提取插件都挂载在“页面解析”(parser)挂载点上。这个挂载点其实是用来解析链接(为后续爬取提供URL)和提供一些搜索引擎的。易于提取的网页信息(元信息、网页文本)。
4)使用Nutch进行爬虫的二次开发,编写和调试爬虫所需的时间往往是单机爬虫所需时间的十倍以上。学习 Nutch 源码的成本非常高,更何况团队中的每个人都必须了解 Nutch 源码。在调试过程中,会出现程序本身以外的各种问题(hadoop问题、hbase问题)。
5)很多人说Nutch2有gora,可以将数据持久化到avro文件、hbase、mysql等,其实很多人都误解了。这里所说的持久化数据是指在avro、hbase、mysql中存储URL信息(URL管理所需的数据)。不是您要提取的结构化数据。事实上,对于大多数人来说,URL 信息存在于何处并不重要。
6)Nutch2 的版本目前不适合开发。Nutch的官方稳定版是nutch2.2.1,但是这个版本绑定了gora-0.3。如果要使用hbase和nutch(大多数人使用nutch2是为了使用hbase),只能使用版本0.90左右的hbase,相应地,将hadoop版本降低到hadoop0.左右@>2。而且nutch2的官方教程也颇具误导性。Nutch2的教程有两个,分别是Nutch1.x和Nutch2.x。Nutch2.x官网是为了支持hbase0.94而写的。但其实这个Nutch2.x是指Nutch2.3之前和Nutch2.2.1之后的一个版本,在官方SVN中不断更新。而且它'
所以,如果你不是搜索引擎,尽量不要选择 Nutch 作为爬虫。一些团队喜欢跟风。他们坚持选择Nutch来开发精制履带。事实上,这是针对Nutch的声誉。当然,最终的结果往往是项目延期。
如果你在做搜索引擎,Nutch1.x 是一个非常不错的选择。Nutch1.x 和 solr 或 es 可以组成一个非常强大的搜索引擎。如果必须使用 Nutch2,建议等到 Nutch2.3 发布。当前的 Nutch2 是一个非常不稳定的版本。
分布式爬虫平台架构图
3.2JAVA爬虫
在这里,将JAVA爬虫划分为一个单独的类别,因为JAVA在网络爬虫的生态系统中非常完善。相关资料也是最全的。这里可能有争议,我只是随便说说。
其实开源网络爬虫(框架)的开发非常简单,前人已经解决了困难和复杂的问题(如DOM树解析定位、字符集检测、海量URL去重等),可以据说没有技术含量。. 包括Nutch,其实Nutch的技术难点就是开发hadoop,代码本身也很简单。从某种意义上说,网络爬虫类似于遍历本机的文件以查找文件中的信息。没有任何困难。选择开源爬虫框架的原因是为了省事。比如爬虫的URL管理、线程池等模块,任何人都可以做,但是需要一段时间的调试和修改才能稳定下来。
对于爬虫的功能。用户比较关心的问题往往是:
1)爬虫是否支持多线程,爬虫可以使用代理,爬虫可以抓取重复数据,爬虫可以抓取JS生成的信息吗?
不支持多线程、不支持代理、不能过滤重复URL的不叫开源爬虫,叫循环执行http请求。
js生成的信息能否被爬取与爬虫本身关系不大。爬虫主要负责遍历网站和下载页面。爬取js产生的信息与网页信息提取模块有关,往往需要模拟浏览器(htmlunit、selenium)来完成。这些模拟浏览器通常需要花费大量时间来处理一个页面。因此,一种策略是利用这些爬虫遍历网站,当遇到需要解析的页面时,将网页的相关信息提交给模拟浏览器,完成对JS生成信息的提取。
2)爬虫可以抓取ajax信息吗?
网页上有一些异步加载的数据。爬取数据有两种方式:使用模拟浏览器(问题1中描述),或者分析ajax的http请求,自己生成ajax请求的url,获取返回的数据。如果你自己生成ajax请求,那么使用开源爬虫有什么意义呢?其实就是利用开源爬虫的线程池和URL管理功能(比如断点爬取)。
如果我已经可以生成我需要的ajax请求(列表),我该如何使用这些爬虫来爬取这些请求呢?
爬虫往往被设计成广度遍历或深度遍历的方式来遍历静态或动态页面。爬取ajax信息属于deepweb(深网)的范畴,虽然大部分爬虫并不直接支持。但它也可以通过某些方式完成。例如,WebCollector 使用广度遍历来遍历 网站。爬虫的第一轮爬取就是爬取种子集(seeds)中的所有url。简单来说就是将生成的ajax请求作为种子,放入爬虫中。使用爬虫对这些种子进行深度为 1 的广度遍历(默认为广度遍历)。
3)爬虫如何爬取待登录的网站?
这些开源爬虫都支持在爬取时指定cookies,而模拟登录主要依赖cookies。至于如何获取cookies,就不是爬虫管理的问题了。您可以手动获取cookies,使用http请求模拟登录,或者使用模拟浏览器自动登录。
4)爬虫如何从网页中提取信息?
开源爬虫一般会集成网页提取工具。主要支持两种规范:CSSSELECTOR 和 XPATH。至于哪个更好,我这里就不评论了。
5)爬虫是如何保存网页信息的?
有一些爬虫带有一个负责持久性的模块。例如,webmagic 有一个名为 pipeline 的模块。通过简单的配置,爬虫提取的信息可以持久化到文件、数据库等。还有一些爬虫不直接为用户提供数据持久化模块。比如 crawler4j 和 webcollector。让用户在网页处理模块中添加提交数据库的操作。至于用管道模块好不好,就类似于用ORM操作数据库好不好的问题,看你的业务。
6)爬虫被网站拦截了怎么办?
爬虫被网站阻塞,可以通过使用多个代理(随机代理)来解决。但是这些开源爬虫一般不直接支持随机代理的切换。因此,用户经常需要将获取到的agent放入一个全局数组中,并编写一段代码让agent随机获取(从数组中)。
7)网页可以调用爬虫吗?
爬虫的调用是在Web的服务器端调用的。您可以按照平时使用的方式使用它。可以使用这些爬虫。
8)爬虫速度怎么样?
单机开源爬虫的速度基本可以用到本地网速的极限。爬虫速度慢往往是因为用户减少了线程数,网速慢,或者数据持久化时与数据库的交互慢。而这些东西往往是由用户的机器和二次开发的代码决定的。这些开源爬虫的速度非常好。
9) 明明代码写对了,但是数据爬不出来。爬虫有问题吗?不同的爬虫可以解决吗?
如果代码写得正确,无法爬取数据,其他爬虫也将无法爬取。在这种情况下,要么是 网站 阻止了您,要么您抓取的数据是由 javascript 生成的。如果无法爬取数据,则无法通过更改爬虫来解决。
10)哪个爬虫可以判断网站是否已经爬完,哪个爬虫可以根据主题爬取?
爬虫无法判断网站是否已经爬完,只能尽量覆盖。
至于根据主题爬,爬虫把内容爬下来后就知道主题是什么了。因此,通常是整体爬下来,然后对内容进行过滤。如果爬取的范围太广,可以通过限制 URL 正则化来缩小范围。
11)哪个爬虫的设计模式和架构比较好?
设计模式是胡说八道。都说软件设计模式不错,软件开发后总结了几种设计模式。设计模式对软件开发没有指导意义。使用设计模式设计爬虫只会让爬虫的设计更加臃肿。
至于架构,目前开源爬虫主要是设计详细的数据结构,比如爬取线程池、任务队列等,大家都可以控制。爬虫的业务太简单了,用任何框架都谈不上。
所以对于 JAVA 开源爬虫,我认为,只要找到一个运行良好的。如果业务复杂,使用哪个爬虫,只能通过复杂的二次开发来满足需求。
3.3 非JAVA爬虫
在非JAVA语言编写的爬虫中,不乏优秀的爬虫。这里提取为一个类别,不是为了讨论爬虫本身的好坏,而是为了讨论larbin、scrapy等爬虫对开发成本的影响。
先说python爬虫,python用30行代码就可以完成JAVA50行代码的任务。Python写代码确实很快,但是在调试代码阶段,调试python代码所消耗的时间往往比编码阶段节省的时间要多得多。使用python开发,为了保证程序的正确性和稳定性,需要编写更多的测试模块。当然,如果爬取规模不大,爬取业务也不复杂,用scrapy还是不错的,可以轻松完成爬取任务。
上图是Scrapy的架构图。绿线是数据流。从初始 URL 开始,Scheduler 会将其交给 Downloader 进行下载。下载完成后交给Spider进行分析,将要保存的数据发送到ItemPipeline。那就是对数据进行后处理。此外,可以在数据流通道中安装各种中间件,进行必要的处理。因此,在开发爬虫时,最好先规划好各个模块。我的做法是分别规划下载模块、爬取模块、调度模块、数据存储模块。
对于C++爬虫来说,学习成本会比较大。而且不能只计算一个人的学习成本。如果软件需要一个团队来开发或者移交,那就是很多人的学习成本。软件调试不是那么容易。
还有一些ruby和php爬虫,这里就不多评价了。确实有一些非常小的data采集任务,在ruby或者php中都用得上。但是,要选择这些语言的开源爬虫,一方面需要调查相关的生态系统,另一方面,这些开源爬虫可能存在一些你找不到的bug(很少有人使用它们,而且信息也较少)
4、反爬虫技术
由于搜索引擎的普及,网络爬虫已经成为一种非常流行的网络技术。除了专注于搜索的谷歌、雅虎、微软和百度之外,几乎每个大型门户网站网站都有自己的搜索引擎,大大小小的。可以叫的名字有几十种,不知道的种类有上万种。对于一个内容驱动的网站,难免会被网络爬虫光顾。
一些智能搜索引擎爬虫的爬取频率比较合理,资源消耗也比较小,但是很多不良网络爬虫对网页的爬取能力很差,经常循环重复上百个请求。拿,这种爬虫对中小型网站来说往往是毁灭性的打击,尤其是一些缺乏爬虫编写经验的程序员编写的爬虫,破坏性极大,导致网站访问压力会很大非常大,这将导致 网站 访问缓慢甚至无法访问。
一般网站反爬虫从三个方面进行:用户请求的头文件、用户行为、网站目录和数据加载方式。前两种比较容易遇到,从这些角度来看,大部分网站都是反爬虫。会使用第三种使用ajax的网站,增加了爬取的难度。
4.1 反爬虫通过Headers
反爬取用户请求的头部是最常见的反爬取策略。很多网站会检测header的User-Agent,有的网站会检测Referer(有些资源的防盗链网站就是检测Referer)。如果遇到这样的反爬虫机制,可以直接在爬虫中添加Headers,将浏览器的User-Agent复制到爬虫的Headers中;或者将Referer值改为目标网站域名。对于检测Headers的反爬虫,在爬虫中修改或添加Headers可以很好的绕过。
[评论:它通常很容易被忽略。通过对请求的抓包分析,确定referer,并添加到程序中模拟访问请求的header]
4.2 基于用户行为的反爬虫
网站的另一部分是检测用户行为,比如同一个IP在短时间内多次访问同一个页面,或者同一个账号在短时间内多次执行相同的操作。
htmlunit抓取动态网页(Java爬取博客阅读文章最多)
网站优化 • 优采云 发表了文章 • 0 个评论 • 44 次浏览 • 2022-02-01 02:18
更新,这很尴尬,这个文章博客是阅读最多的文章,但也是最被践踏的。
爬取思路:
所谓动态是指通过请求后台可以动态改变对应的html页面,开始时页面并不是全部显示出来的。
大多数操作都是通过请求完成的,一个请求,一个返回。在大多数网页中,请求往往被开发者隐藏在 js 代码中。
所以将爬取动态网页的思路转化为找到对应的js代码并执行对应的js代码,从而通过java代码实现页面的动态变化。
而当页面能够正确显示的时候,我们就可以像爬静态网页一样爬取数据了!
首先,可以使用htmlunit来模拟鼠标点击事件,很容易实现:
/**
* 通过htmlunit来获得一些搜狗的网址。
* 通过模拟鼠标点击事件来实现
* @param key
* @return
* @throws Exception
*/
public String getNextUrl(String key){
String page = new String();
try {
WebClient webClient = new WebClient();
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(false);
//去拿网页
HtmlPage htmlPage = webClient.getPage("http://pic.sogou.com/");
//得到表单
HtmlForm form = htmlPage.getFormByName("searchForm");
//得到提交按钮
HtmlSubmitInput button = form.getInputByValue("搜狗搜索");
//得到输入框
HtmlTextInput textField = form.getInputByName("query");
//输入内容
textField.setValueAttribute(key);
//点一下按钮
HtmlPage nextPage = button.click();
String str = nextPage.toString();
page = cutString(str);
webClient.close();
} catch (Exception e) {
e.printStackTrace();
}
return page;
}
如上图,我只是通过java代码将关键字填入搜索我的,然后通过getInputByValue方法得到按钮控件,最后直接button.click(),
即可以模拟点击,将点击后返回的http请求解析成html页面。
这个功能其实很强大。比如你可以使用这个功能来模拟抢票,或者使用点击事件,加上搜索相关知识,将整个系统下线,并以html的形式保存。
接下来就是使用强大的htmlunit来执行js代码了。
先写一个简单的jsp页面:
Insert title here
原数字
function change(value) {
document.getElementById("test").innerHTML = value;
return "hello htmlUnit";
}
从上面可以看出,jsp页面很简单,只是一个函数变化,用来调用htmlUnit。
接下来是一个使用 htmlunit 的类。此类通过支持 JavaScript 解释器来工作,
然后将自己编写的JavaScript代码嵌入到页面中执行,获取执行后的返回结果返回页面。
package com.blog.anla;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class TestMyOwnPage {
private void action() {
WebClient webClient = new WebClient();
try {
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true); // 设置支持JavaScript。
// 去拿网页
HtmlPage htmlPage = webClient
.getPage("http://localhost:8989/testHtmlScrop/index.jsp");
String s = "更改后的数字";
ScriptResult t = htmlPage.executeJavaScript("change(\"" + s
+ "\");", "injected script", 500);
// 这里是在500行插入这一小行JavaScript代码段,因为如果在默认的1行,那不会有结果
// 因为js是顺序执行的,当你执行第一行js代码时,可能还没有渲染body里面的标签。
HtmlPage myPage = (HtmlPage) t.getNewPage();
String nextPage = myPage.asXml().toString();
String nextPage2 = myPage.asText().toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
webClient.close();
}
}
public static void main(String[] args) {
TestMyOwnPage tmop = new TestMyOwnPage();
tmop.action();
}
}
t.getNewPage()中有两个属性,一个是
javaScriptResult:执行这段代码后返回的结果,如果有(我上面写的,返回hello htmlunit),如果没有(返回Undefined)。
newPage_:执行此代码后返回的整个页面。
结果如下:
这段代码执行的最终结果如下:
asXml():将整个页面的html代码返回给我们:
而asText()只返回页面上可以显示的值,即head标签和label标签:
这种执行思路还可以动态执行相应的js代码,从而爬取需要的数据。
-------------------------------------------------- --------------------------------------2017 年 7 月更新---------- -------------------------------------- -------------------------------------------------- -----
这两天一直在做一个关于网络爬虫的系统
然而,当我开始攀爬时,我发现了一个问题。js的动态页面爬不下来。
网上找了很多方法,google也问了,主要是指htmlunit,下面是核心代码,
使用htmlunit的主要目的是模拟浏览器操作,因为有些链接点击无法直接通过src获取url,一般使用JavaScript。
简单拼接后的URL,所以用htmlunit直接模拟浏览器点击比较简单。
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true); //启用JS解释器,默认为true
webClient.getOptions().setCssEnabled(false); //禁用css支持
webClient.getOptions().setThrowExceptionOnScriptError(false); //js运行错误时,是否抛出异常
webClient.getOptions().setTimeout(20000);
HtmlPage page = wc.getPage("http://www.hao123.com");
//我认为这个最重要
String pageXml = page.asXml(); //以xml的形式获取响应文本
/**jsoup解析文档*/
Document doc = Jsoup.parse(pageXml, "http://cq.qq.com");
这个时候,就可以得到jsoup中的document对象了,接下来就好写了,就像爬普通静态网页一样了。
不过,webclient解析是还是会出现一些问题,js的问题,
主要是由于目标url的js写的有些问题,但在实际的浏览器中却会忽略,eclipse中会报异常。
今天看,好多人踩了,可能我当时没认真写博客吧。如果想找java爬虫项目,可以去我的专栏
图片搜索包括使用jsoup爬取图片,以及lire索引和搜索图片。
玫瑰会在你的手中留下挥之不去的芬芳。有什么问题可以多多讨论! 查看全部
htmlunit抓取动态网页(Java爬取博客阅读文章最多)
更新,这很尴尬,这个文章博客是阅读最多的文章,但也是最被践踏的。
爬取思路:
所谓动态是指通过请求后台可以动态改变对应的html页面,开始时页面并不是全部显示出来的。
大多数操作都是通过请求完成的,一个请求,一个返回。在大多数网页中,请求往往被开发者隐藏在 js 代码中。
所以将爬取动态网页的思路转化为找到对应的js代码并执行对应的js代码,从而通过java代码实现页面的动态变化。
而当页面能够正确显示的时候,我们就可以像爬静态网页一样爬取数据了!
首先,可以使用htmlunit来模拟鼠标点击事件,很容易实现:
/**
* 通过htmlunit来获得一些搜狗的网址。
* 通过模拟鼠标点击事件来实现
* @param key
* @return
* @throws Exception
*/
public String getNextUrl(String key){
String page = new String();
try {
WebClient webClient = new WebClient();
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(false);
//去拿网页
HtmlPage htmlPage = webClient.getPage("http://pic.sogou.com/");
//得到表单
HtmlForm form = htmlPage.getFormByName("searchForm");
//得到提交按钮
HtmlSubmitInput button = form.getInputByValue("搜狗搜索");
//得到输入框
HtmlTextInput textField = form.getInputByName("query");
//输入内容
textField.setValueAttribute(key);
//点一下按钮
HtmlPage nextPage = button.click();
String str = nextPage.toString();
page = cutString(str);
webClient.close();
} catch (Exception e) {
e.printStackTrace();
}
return page;
}
如上图,我只是通过java代码将关键字填入搜索我的,然后通过getInputByValue方法得到按钮控件,最后直接button.click(),
即可以模拟点击,将点击后返回的http请求解析成html页面。
这个功能其实很强大。比如你可以使用这个功能来模拟抢票,或者使用点击事件,加上搜索相关知识,将整个系统下线,并以html的形式保存。
接下来就是使用强大的htmlunit来执行js代码了。
先写一个简单的jsp页面:
Insert title here
原数字
function change(value) {
document.getElementById("test").innerHTML = value;
return "hello htmlUnit";
}
从上面可以看出,jsp页面很简单,只是一个函数变化,用来调用htmlUnit。
接下来是一个使用 htmlunit 的类。此类通过支持 JavaScript 解释器来工作,
然后将自己编写的JavaScript代码嵌入到页面中执行,获取执行后的返回结果返回页面。
package com.blog.anla;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class TestMyOwnPage {
private void action() {
WebClient webClient = new WebClient();
try {
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true); // 设置支持JavaScript。
// 去拿网页
HtmlPage htmlPage = webClient
.getPage("http://localhost:8989/testHtmlScrop/index.jsp");
String s = "更改后的数字";
ScriptResult t = htmlPage.executeJavaScript("change(\"" + s
+ "\");", "injected script", 500);
// 这里是在500行插入这一小行JavaScript代码段,因为如果在默认的1行,那不会有结果
// 因为js是顺序执行的,当你执行第一行js代码时,可能还没有渲染body里面的标签。
HtmlPage myPage = (HtmlPage) t.getNewPage();
String nextPage = myPage.asXml().toString();
String nextPage2 = myPage.asText().toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
webClient.close();
}
}
public static void main(String[] args) {
TestMyOwnPage tmop = new TestMyOwnPage();
tmop.action();
}
}
t.getNewPage()中有两个属性,一个是
javaScriptResult:执行这段代码后返回的结果,如果有(我上面写的,返回hello htmlunit),如果没有(返回Undefined)。
newPage_:执行此代码后返回的整个页面。
结果如下:
这段代码执行的最终结果如下:
asXml():将整个页面的html代码返回给我们:
而asText()只返回页面上可以显示的值,即head标签和label标签:
这种执行思路还可以动态执行相应的js代码,从而爬取需要的数据。
-------------------------------------------------- --------------------------------------2017 年 7 月更新---------- -------------------------------------- -------------------------------------------------- -----
这两天一直在做一个关于网络爬虫的系统
然而,当我开始攀爬时,我发现了一个问题。js的动态页面爬不下来。
网上找了很多方法,google也问了,主要是指htmlunit,下面是核心代码,
使用htmlunit的主要目的是模拟浏览器操作,因为有些链接点击无法直接通过src获取url,一般使用JavaScript。
简单拼接后的URL,所以用htmlunit直接模拟浏览器点击比较简单。
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true); //启用JS解释器,默认为true
webClient.getOptions().setCssEnabled(false); //禁用css支持
webClient.getOptions().setThrowExceptionOnScriptError(false); //js运行错误时,是否抛出异常
webClient.getOptions().setTimeout(20000);
HtmlPage page = wc.getPage("http://www.hao123.com");
//我认为这个最重要
String pageXml = page.asXml(); //以xml的形式获取响应文本
/**jsoup解析文档*/
Document doc = Jsoup.parse(pageXml, "http://cq.qq.com");
这个时候,就可以得到jsoup中的document对象了,接下来就好写了,就像爬普通静态网页一样了。
不过,webclient解析是还是会出现一些问题,js的问题,
主要是由于目标url的js写的有些问题,但在实际的浏览器中却会忽略,eclipse中会报异常。
今天看,好多人踩了,可能我当时没认真写博客吧。如果想找java爬虫项目,可以去我的专栏
图片搜索包括使用jsoup爬取图片,以及lire索引和搜索图片。
玫瑰会在你的手中留下挥之不去的芬芳。有什么问题可以多多讨论!
htmlunit抓取动态网页(所说的问题试试)
网站优化 • 优采云 发表了文章 • 0 个评论 • 58 次浏览 • 2022-01-30 07:11
没错,最后我还是用 Selenium 来实现我在上一篇文章中提到的问题。我没有尝试其他任何东西。我只试过火狐引擎。整体效果我还是可以接受的。
继续昨天的话题,既然要实现上一篇提到的问题,就需要一个可以执行js代码的框架。我的首选是htmlunit,先简单介绍一下htmlunit。以下段落摘自互联网。
htmlunit 是一个开源的java页面分析工具。启动htmlunit后,会在底层启动一个非界面浏览器。用户可以指定浏览器类型:firefox、ie等。如果不指定,默认使用INTERNET_EXPLORER_7:
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
只需调用:
HtmlPage 页面 = webClient.getPage(url);
可以获取页面的 HtmlPage 表示,然后通过:
InputStream 是 = targetPage.getWebResponse().getContentAsStream()
可以获取页面的输入流,从而获取页面的源代码,对于网络爬虫项目非常有用。
当然,你也可以从page中获取更多的页面元素。
重要的是,HtmlUnit 提供对执行 javascript 的支持:
page.executeJavaScript(javascript)
执行js后,返回一个ScriptResult对象,通过该对象可以获取执行js后的页面等信息。默认情况下,执行完js后,内部浏览器会进行页面跳转,跳转到执行完js后生成的新页面。如果js执行失败,则不会执行页面跳转。
最后可以通过page.executeJavaScript(javascript).getNewPage()获取执行的页面。也就是说,这里需要人为地执行javascript,这显然不符合我的初衷。另外,我的水平可能太差了。我在爬新浪新闻的页面时总是出错。根据网络上的查询结果,最可能的错误原因是htmlunit在执行一些带参数的请求时,由于参数顺序或者编码问题,请求失败,报错。关键是,运行它后我没有得到我需要的结果。
然后我寻找另一种解决方案。这时,我找到了 SeleniumWebDriver,这是我需要的解决方案。
参考资料和例子,就可以开始使用了。示例代码如下。
<p> 1 File pathToBinary = new File("D:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe");
2 FirefoxBinary ffBinary = new FirefoxBinary(pathToBinary);
3 FirefoxProfile firefoxProfile = new FirefoxProfile();
4 FirefoxDriver driver = new FirefoxDriver(ffBinary,firefoxProfile);
5
6
7 driver.get("http://cq.qq.com/baoliao/detail.htm?294064");
8
9 ArrayList list = new ArrayList();
10 list.add("http://www.sina.com.cn");
11 list.add("http://www.sohu.com");
12 list.add("http://www.163.com");
13 list.add("http://www.qq.com");
14
15 long start,end;
16
17 for(int i=0;i 查看全部
htmlunit抓取动态网页(所说的问题试试)
没错,最后我还是用 Selenium 来实现我在上一篇文章中提到的问题。我没有尝试其他任何东西。我只试过火狐引擎。整体效果我还是可以接受的。
继续昨天的话题,既然要实现上一篇提到的问题,就需要一个可以执行js代码的框架。我的首选是htmlunit,先简单介绍一下htmlunit。以下段落摘自互联网。
htmlunit 是一个开源的java页面分析工具。启动htmlunit后,会在底层启动一个非界面浏览器。用户可以指定浏览器类型:firefox、ie等。如果不指定,默认使用INTERNET_EXPLORER_7:
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
只需调用:
HtmlPage 页面 = webClient.getPage(url);
可以获取页面的 HtmlPage 表示,然后通过:
InputStream 是 = targetPage.getWebResponse().getContentAsStream()
可以获取页面的输入流,从而获取页面的源代码,对于网络爬虫项目非常有用。
当然,你也可以从page中获取更多的页面元素。
重要的是,HtmlUnit 提供对执行 javascript 的支持:
page.executeJavaScript(javascript)
执行js后,返回一个ScriptResult对象,通过该对象可以获取执行js后的页面等信息。默认情况下,执行完js后,内部浏览器会进行页面跳转,跳转到执行完js后生成的新页面。如果js执行失败,则不会执行页面跳转。
最后可以通过page.executeJavaScript(javascript).getNewPage()获取执行的页面。也就是说,这里需要人为地执行javascript,这显然不符合我的初衷。另外,我的水平可能太差了。我在爬新浪新闻的页面时总是出错。根据网络上的查询结果,最可能的错误原因是htmlunit在执行一些带参数的请求时,由于参数顺序或者编码问题,请求失败,报错。关键是,运行它后我没有得到我需要的结果。
然后我寻找另一种解决方案。这时,我找到了 SeleniumWebDriver,这是我需要的解决方案。
参考资料和例子,就可以开始使用了。示例代码如下。
<p> 1 File pathToBinary = new File("D:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe");
2 FirefoxBinary ffBinary = new FirefoxBinary(pathToBinary);
3 FirefoxProfile firefoxProfile = new FirefoxProfile();
4 FirefoxDriver driver = new FirefoxDriver(ffBinary,firefoxProfile);
5
6
7 driver.get("http://cq.qq.com/baoliao/detail.htm?294064");
8
9 ArrayList list = new ArrayList();
10 list.add("http://www.sina.com.cn");
11 list.add("http://www.sohu.com");
12 list.add("http://www.163.com");
13 list.add("http://www.qq.com");
14
15 long start,end;
16
17 for(int i=0;i
htmlunit抓取动态网页(1.HtmlUnit中文文档获取页面中特定的元素tips:1.)
网站优化 • 优采云 发表了文章 • 0 个评论 • 128 次浏览 • 2022-01-30 06:12
1.HtmlUnit 简介
HtmlUnit 是一个 java 无界面浏览器库。它模拟 HTML 文档并提供相应的 API,允许您调用页面、填写表单、单击链接等,就像您在“普通”浏览器中所做的那样。它具有相当不错的 JavaScript 支持(仍在改进),甚至能够处理相当复杂的 AJAX 库,根据使用的配置模拟 Chrome、Firefox 或 Internet Explorer。它通常用于测试目的或从 网站 检索信息。
HtmlUnit 不是一个通用的单元测试框架。它是一种模拟浏览器以进行测试的方法,旨在用于其他测试框架,例如 JUnit 或 TestNG。有关介绍,请参见文档“HtmlUnit 入门”。HtmlUnit 用作不同的开源工具,如 Canoo WebTest、JWebUnit、WebDriver、JSFUnit、WETATOR、Celerity、Spring MVC Test HtmlUnit 作为底层“浏览器”。
HtmlUnit 最初由 Gargoyle Software 的 Mike Bowler 编写,并在 Apache 2 许可下发布。从那时起,它收到了许多其他开发者的贡献,今天将得到他们的帮助。
几年前,我在为购物网站 做数据采集工作时偶然发现了HtmlUnit。记得当时页面上的价格数据是抓不到的,httpfox也无法追踪到价格数据的url。就在我手足无措的时候,HtmlUnit出现了,帮我解决了问题。所以今天我要说声谢谢并向大家推荐HtmlUnit。
2.htmlUnit 中文文档
3.1 获取页面的TITLE、XML代码、文本
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//创建一个webclient
WebClient webClient = new WebClient();
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
//获取页面
HtmlPage page = webClient.getPage("http://www.baidu.com/");
//获取页面的TITLE
str = page.getTitleText();
System.out.println(str);
//获取页面的XML代码
str = page.asXml();
System.out.println(str);
//获取页面的文本
str = page.asText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}
3.2 用不同版本的浏览器打开
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//使用FireFox读取网页
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = webClient.getPage("http://www.baidu.com/");
str = page.getTitleText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}
3.3 在页面中查找特定元素
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//通过id获得"百度一下"按钮
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
System.out.println(btn.getDefaultValue());
//关闭webclient
webClient.closeAllWindows();
}
}
提示:有些元素没有 id 和 name 或其他节点。您可以通过查找其子节点和父节点之间的规律性来获取该元素。具体方法请参考:
它的核心代码是:
final HtmlPage nextPage = ((DomElement)(htmlpage.getElementByName("key").getParentNode().getParentNode())).getLastElementChild().click();
3.4 元素检索
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//查找所有div
List hbList = page.getByXPath("//div");
HtmlDivision hb = (HtmlDivision)hbList.get(0);
System.out.println(hb.toString());
//查找并获取特定input
List inputList = page.getByXPath("//input[@id='su']");
HtmlInput input = (HtmlInput)inputList.get(0);
System.out.println(input.toString());
//关闭webclient
webClient.closeAllWindows();
}
}
3.5 提交搜索
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//获取搜索输入框并提交搜索内容
HtmlInput input = (HtmlInput)page.getHtmlElementById("kw");
System.out.println(input.toString());
input.setValueAttribute("ymd");
System.out.println(input.toString());
//获取搜索按钮并点击
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
HtmlPage page2 = btn.click();
//输出新页面的文本
System.out.println(page2.asText());
}
}
3.htmlUnit方法介绍
一、环境介绍
因为我是在自己的spring boot项目中引入的,所以只需要在pom文件中添加依赖即可
net.sourceforge.htmlunit
htmlunit
2.41.0
如果只是爬一点js 网站 建议改一下下面的依赖
net.sourceforge.htmlunit
htmlunit
2.23
两者的区别将在后面讨论。当然,如果你用的不是maven项目(没有pom),可以去官网下载源码库
二、使用
HtmlUnit 使用起来非常简单。使用的时候可以去官网手册查看语法。其实说明书只是介绍,下面听我说就够了;
1、创建客户端并配置客户端
final String url ="https:****";//大家这可以填自己爬虫的地址
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_68);//创建火狐浏览器 2.23版本是FIREFOX_45 new不写参数是默认浏览器
webClient.getOptions().setCssEnabled(false);//(屏蔽)css 因为css并不影响我们抓取数据 反而影响网页渲染效率
webClient.getOptions().setThrowExceptionOnScriptError(false);//(屏蔽)异常
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//(屏蔽)日志
webClient.getOptions().setJavaScriptEnabled(true);//加载js脚本
webClient.getOptions().setTimeout(50000);//设置超时时间
webClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置ajax
HtmlPage htmlPage = webClient.getPage(url);//将客户端获取的树形结构转化为HtmlPage
Thread.sleep(10000);//主线程休眠10秒 让客户端有时间执行js代码 也可以写成webClient.waitForBackgroundJavaScript(1000)
有一个等待js执行,2.41.0非常兼容很多js,但是2.3总是有问题不能刷新网页,2. 41.0 打印也很详细,执行过程比较慢,可能是慢而细致。
远程地址页差不多就到这里了。我们现在要做的就是解析dom节点并填写数据来模拟点击等事件。如果要打印出来 htmlPage.asText() 输出 htmlPage 节点的文本 htmlPage.asXml() 输出 htmlPage 节点的 xml 代码
2、节点获取
在这个链接中,建议准备一点前端知识
HtmlUnit 提供了两种获取节点的方法
XPath 查询:
更详细的xpath解释:
final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
//get list of all divs
final List divs = htmlPage .getByXPath("//div");
//get div which has a 'name' attribute of 'John'
final HtmlDivision div = (HtmlDivision) htmlPage .getByXPath("//div[@name='John']").get(0);
css 选择器:(我更喜欢它)
final DomNodeList divs = htmlPage .querySelectorAll("div");
for (DomNode div : divs) {
....
}
//get div which has the id 'breadcrumbs'
final DomNode div = htmlPage .querySelector("div#breadcrumbs");
css给出了一个集合查询querySelectorAll和一个单一查询querySelector,如果你没有基础,我给你下面的例子来理解:
htmlPage.querySelectorAll("div") 返回 htmlPage 下面的 div 标签集合
htmlPage.querySelector("div:nth-child(1)") 返回htmlPage下面的div的第一个div
htmlPage .querySelector(".submit") 返回htmlPage下的第一个class=submit标签
htmlPage .querySelector("#submit") 返回htmlPage下id=submit的第一个标签
htmlPage.querySelector("div.submit") 返回htmlPage下第一个带有submit类的div标签
htmlPage.querySelector("div[id='submit']") 返回 htmlPage 下面的第一个 div 标签,id 为 submit
上面的枚举方式相信就够了,如果还不够,可以参考css选择器
下面列出了常见的html标签和HtmlUnit类的对应关系
div -> HtmlDivision
div集合 -> DomNodeList
fieldSet -> HtmlFieldSet
form -> HtmlForm
button -> HtmlButton
a -> HtmlAnchor
-> HtmlXxxInput
( -> HtmlTextInput)
table -> HtmlTable
tr -> HtmlTableRow
td -> TableDataCell
节点的属性样式有一个setAttribute()方法,setNodeValue()设置节点值。你的英语突然提高了吗?几乎所有的标签都能找到对应的类。来看看我的实战:这是一个在线填写温度的excel文档。如果你访问并更改地址,他会提示登录页面上有一个登录按钮。登录按钮,我们现在模拟打开自动登录框:
//这段代码是为了让网页的的某个按钮加载出来之后再执行下面的代码
while (htmlPage.querySelector("#header-login-btn")==null) {
synchronized (htmlPage) {
htmlPage.wait(1000);
}
}
HtmlButton login = htmlPage.querySelector("#header-login-btn");//获取到登陆按钮
if (login!=null){//如果网页上没这个按钮你还要去获取他只会得到一个空对象,所以我们用空的方式可以判断网页上是否有这个按钮
System.out.println("-----未登录测试-----");
htmlPage=login.click();//模拟按钮点击后要将网页返回回来方便动态更新数据
System.out.println(htmlPage.asText());
HtmlAnchor switcher_plogin = htmlPage.querySelector("a[id='switcher_plogin']");
if (switcher_plogin!=null) {//帐号密码登录
System.out.println("-----点击了帐号密码登陆-----");
htmlPage = switcher_plogin.click();
System.out.println(htmlPage.asText());
}
}
System.out.println(htmlPage.asText());
webClient.close();
爬虫最重要的一步就是先调试网页,有哪些按钮,点击哪些,设置哪些值。毕竟,我们要用代码来调度代码。
**扩展:**如果要从网页中获取数据或下载文件,仅依靠HtmlUnit解析是不够的。推荐使用Jsoup库,可以和HtmlUnit一起使用,比较好用,这里就不一一列举了。
三、实现一个小demo
注意:不是所有htmlunit引用的jar包都会报奇怪的错误
使用maven方法更方便
参考: 查看全部
htmlunit抓取动态网页(1.HtmlUnit中文文档获取页面中特定的元素tips:1.)
1.HtmlUnit 简介
HtmlUnit 是一个 java 无界面浏览器库。它模拟 HTML 文档并提供相应的 API,允许您调用页面、填写表单、单击链接等,就像您在“普通”浏览器中所做的那样。它具有相当不错的 JavaScript 支持(仍在改进),甚至能够处理相当复杂的 AJAX 库,根据使用的配置模拟 Chrome、Firefox 或 Internet Explorer。它通常用于测试目的或从 网站 检索信息。
HtmlUnit 不是一个通用的单元测试框架。它是一种模拟浏览器以进行测试的方法,旨在用于其他测试框架,例如 JUnit 或 TestNG。有关介绍,请参见文档“HtmlUnit 入门”。HtmlUnit 用作不同的开源工具,如 Canoo WebTest、JWebUnit、WebDriver、JSFUnit、WETATOR、Celerity、Spring MVC Test HtmlUnit 作为底层“浏览器”。
HtmlUnit 最初由 Gargoyle Software 的 Mike Bowler 编写,并在 Apache 2 许可下发布。从那时起,它收到了许多其他开发者的贡献,今天将得到他们的帮助。
几年前,我在为购物网站 做数据采集工作时偶然发现了HtmlUnit。记得当时页面上的价格数据是抓不到的,httpfox也无法追踪到价格数据的url。就在我手足无措的时候,HtmlUnit出现了,帮我解决了问题。所以今天我要说声谢谢并向大家推荐HtmlUnit。
2.htmlUnit 中文文档
3.1 获取页面的TITLE、XML代码、文本

import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//创建一个webclient
WebClient webClient = new WebClient();
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
//获取页面
HtmlPage page = webClient.getPage("http://www.baidu.com/");
//获取页面的TITLE
str = page.getTitleText();
System.out.println(str);
//获取页面的XML代码
str = page.asXml();
System.out.println(str);
//获取页面的文本
str = page.asText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}

3.2 用不同版本的浏览器打开

import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//使用FireFox读取网页
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = webClient.getPage("http://www.baidu.com/");
str = page.getTitleText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}

3.3 在页面中查找特定元素
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//通过id获得"百度一下"按钮
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
System.out.println(btn.getDefaultValue());
//关闭webclient
webClient.closeAllWindows();
}
}
提示:有些元素没有 id 和 name 或其他节点。您可以通过查找其子节点和父节点之间的规律性来获取该元素。具体方法请参考:
它的核心代码是:
final HtmlPage nextPage = ((DomElement)(htmlpage.getElementByName("key").getParentNode().getParentNode())).getLastElementChild().click();
3.4 元素检索

public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//查找所有div
List hbList = page.getByXPath("//div");
HtmlDivision hb = (HtmlDivision)hbList.get(0);
System.out.println(hb.toString());
//查找并获取特定input
List inputList = page.getByXPath("//input[@id='su']");
HtmlInput input = (HtmlInput)inputList.get(0);
System.out.println(input.toString());
//关闭webclient
webClient.closeAllWindows();
}
}

3.5 提交搜索

public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//获取搜索输入框并提交搜索内容
HtmlInput input = (HtmlInput)page.getHtmlElementById("kw");
System.out.println(input.toString());
input.setValueAttribute("ymd");
System.out.println(input.toString());
//获取搜索按钮并点击
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
HtmlPage page2 = btn.click();
//输出新页面的文本
System.out.println(page2.asText());
}
}

3.htmlUnit方法介绍
一、环境介绍
因为我是在自己的spring boot项目中引入的,所以只需要在pom文件中添加依赖即可
net.sourceforge.htmlunit
htmlunit
2.41.0
如果只是爬一点js 网站 建议改一下下面的依赖
net.sourceforge.htmlunit
htmlunit
2.23
两者的区别将在后面讨论。当然,如果你用的不是maven项目(没有pom),可以去官网下载源码库
二、使用
HtmlUnit 使用起来非常简单。使用的时候可以去官网手册查看语法。其实说明书只是介绍,下面听我说就够了;
1、创建客户端并配置客户端
final String url ="https:****";//大家这可以填自己爬虫的地址
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_68);//创建火狐浏览器 2.23版本是FIREFOX_45 new不写参数是默认浏览器
webClient.getOptions().setCssEnabled(false);//(屏蔽)css 因为css并不影响我们抓取数据 反而影响网页渲染效率
webClient.getOptions().setThrowExceptionOnScriptError(false);//(屏蔽)异常
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//(屏蔽)日志
webClient.getOptions().setJavaScriptEnabled(true);//加载js脚本
webClient.getOptions().setTimeout(50000);//设置超时时间
webClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置ajax
HtmlPage htmlPage = webClient.getPage(url);//将客户端获取的树形结构转化为HtmlPage
Thread.sleep(10000);//主线程休眠10秒 让客户端有时间执行js代码 也可以写成webClient.waitForBackgroundJavaScript(1000)
有一个等待js执行,2.41.0非常兼容很多js,但是2.3总是有问题不能刷新网页,2. 41.0 打印也很详细,执行过程比较慢,可能是慢而细致。
远程地址页差不多就到这里了。我们现在要做的就是解析dom节点并填写数据来模拟点击等事件。如果要打印出来 htmlPage.asText() 输出 htmlPage 节点的文本 htmlPage.asXml() 输出 htmlPage 节点的 xml 代码
2、节点获取
在这个链接中,建议准备一点前端知识
HtmlUnit 提供了两种获取节点的方法
XPath 查询:
更详细的xpath解释:
final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
//get list of all divs
final List divs = htmlPage .getByXPath("//div");
//get div which has a 'name' attribute of 'John'
final HtmlDivision div = (HtmlDivision) htmlPage .getByXPath("//div[@name='John']").get(0);
css 选择器:(我更喜欢它)
final DomNodeList divs = htmlPage .querySelectorAll("div");
for (DomNode div : divs) {
....
}
//get div which has the id 'breadcrumbs'
final DomNode div = htmlPage .querySelector("div#breadcrumbs");
css给出了一个集合查询querySelectorAll和一个单一查询querySelector,如果你没有基础,我给你下面的例子来理解:
htmlPage.querySelectorAll("div") 返回 htmlPage 下面的 div 标签集合
htmlPage.querySelector("div:nth-child(1)") 返回htmlPage下面的div的第一个div
htmlPage .querySelector(".submit") 返回htmlPage下的第一个class=submit标签
htmlPage .querySelector("#submit") 返回htmlPage下id=submit的第一个标签
htmlPage.querySelector("div.submit") 返回htmlPage下第一个带有submit类的div标签
htmlPage.querySelector("div[id='submit']") 返回 htmlPage 下面的第一个 div 标签,id 为 submit
上面的枚举方式相信就够了,如果还不够,可以参考css选择器
下面列出了常见的html标签和HtmlUnit类的对应关系
div -> HtmlDivision
div集合 -> DomNodeList
fieldSet -> HtmlFieldSet
form -> HtmlForm
button -> HtmlButton
a -> HtmlAnchor
-> HtmlXxxInput
( -> HtmlTextInput)
table -> HtmlTable
tr -> HtmlTableRow
td -> TableDataCell
节点的属性样式有一个setAttribute()方法,setNodeValue()设置节点值。你的英语突然提高了吗?几乎所有的标签都能找到对应的类。来看看我的实战:这是一个在线填写温度的excel文档。如果你访问并更改地址,他会提示登录页面上有一个登录按钮。登录按钮,我们现在模拟打开自动登录框:
//这段代码是为了让网页的的某个按钮加载出来之后再执行下面的代码
while (htmlPage.querySelector("#header-login-btn")==null) {
synchronized (htmlPage) {
htmlPage.wait(1000);
}
}
HtmlButton login = htmlPage.querySelector("#header-login-btn");//获取到登陆按钮
if (login!=null){//如果网页上没这个按钮你还要去获取他只会得到一个空对象,所以我们用空的方式可以判断网页上是否有这个按钮
System.out.println("-----未登录测试-----");
htmlPage=login.click();//模拟按钮点击后要将网页返回回来方便动态更新数据
System.out.println(htmlPage.asText());
HtmlAnchor switcher_plogin = htmlPage.querySelector("a[id='switcher_plogin']");
if (switcher_plogin!=null) {//帐号密码登录
System.out.println("-----点击了帐号密码登陆-----");
htmlPage = switcher_plogin.click();
System.out.println(htmlPage.asText());
}
}
System.out.println(htmlPage.asText());
webClient.close();
爬虫最重要的一步就是先调试网页,有哪些按钮,点击哪些,设置哪些值。毕竟,我们要用代码来调度代码。
**扩展:**如果要从网页中获取数据或下载文件,仅依靠HtmlUnit解析是不够的。推荐使用Jsoup库,可以和HtmlUnit一起使用,比较好用,这里就不一一列举了。
三、实现一个小demo
注意:不是所有htmlunit引用的jar包都会报奇怪的错误
使用maven方法更方便
参考:
htmlunit抓取动态网页(基于Webmagic的动态网页爬虫系统-DynCrawler.系统)
网站优化 • 优采云 发表了文章 • 0 个评论 • 69 次浏览 • 2022-01-29 17:16
概括:
随着网页数量的爆炸式增长,传统的中心化爬虫难以满足实际应用。此外,Ajax 技术在 Web 应用中的广泛普及,给传统的 Web 开发带来了新的革命。为了提高用户体验,用户可以与远程服务器进行良好的交互。典型应用包括校园BBS、博客网站等,这些大量动态网页的出现给传统的网络爬虫带来了巨大的挑战。障碍。它影响爬虫的效率,也影响网页内容的获取。针对以上两个问题,本文设计了一种基于WebMagic爬虫框架的分布式动态网络爬虫系统Dis-Dyn Crawler。系统采用SOA架构为了提高解析效率,系统将HtmlUnit所需的JavaScript等文件缓存在Redis数据库中,并进行页面渲染。无需每次都从网络下载,减少网络请求,提高解析效率;异步页面下载器的实现进一步提高了系统的整体效率。本文从功能和性能两个方面对Dis-Dyn爬虫系统进行了分析。.通过与现有分布式网络爬虫工具的爬取能力对比,验证了基于Webmagic的动态网络爬虫是高效的。通过与现有动态网页解析工具的对比,验证了本文提出的Dis-Dyn爬虫系统是高效的。效率和可行性。
展开 查看全部
htmlunit抓取动态网页(基于Webmagic的动态网页爬虫系统-DynCrawler.系统)
概括:
随着网页数量的爆炸式增长,传统的中心化爬虫难以满足实际应用。此外,Ajax 技术在 Web 应用中的广泛普及,给传统的 Web 开发带来了新的革命。为了提高用户体验,用户可以与远程服务器进行良好的交互。典型应用包括校园BBS、博客网站等,这些大量动态网页的出现给传统的网络爬虫带来了巨大的挑战。障碍。它影响爬虫的效率,也影响网页内容的获取。针对以上两个问题,本文设计了一种基于WebMagic爬虫框架的分布式动态网络爬虫系统Dis-Dyn Crawler。系统采用SOA架构为了提高解析效率,系统将HtmlUnit所需的JavaScript等文件缓存在Redis数据库中,并进行页面渲染。无需每次都从网络下载,减少网络请求,提高解析效率;异步页面下载器的实现进一步提高了系统的整体效率。本文从功能和性能两个方面对Dis-Dyn爬虫系统进行了分析。.通过与现有分布式网络爬虫工具的爬取能力对比,验证了基于Webmagic的动态网络爬虫是高效的。通过与现有动态网页解析工具的对比,验证了本文提出的Dis-Dyn爬虫系统是高效的。效率和可行性。
展开
htmlunit抓取动态网页(没写代码实现获取网页源代码代码模拟按钮的方法)
网站优化 • 优采云 发表了文章 • 0 个评论 • 67 次浏览 • 2022-01-29 11:01
1.几行代码即可获取网页源代码。
final WebClient webClient=new WebClient();
final HtmlPage page=webClient.getPage("http://www.baidu.com");
System.out.println(page.asText()); //asText()是以文本格式显示
System.out.println(page.asXml()); //asXml()是以xml格式显示
webClient.closeAllWindows();
2.模拟文本框和模拟按钮提交,我们来模拟模拟百度搜索关键字的实现。
// 得到浏览器对象,直接New一个就能得到,现在就好比说你得到了一个浏览器了
WebClient webclient = new WebClient();
// 这里是配置一下不加载css和javaScript,因为httpunit对javascript兼容性不太好
webclient.getOptions().setCssEnabled(false);
webclient.getOptions().setJavaScriptEnabled(false);
// 做的第一件事,去拿到这个网页,只需要调用getPage这个方法即可
HtmlPage htmlpage = webclient.getPage("http://baidu.com");
// 根据名字得到一个表单,查看上面这个网页的源代码可以发现表单的名字叫“f”
final HtmlForm form = htmlpage.getFormByName("f");
// 同样道理,获取”百度一下“这个按钮
final HtmlSubmitInput button = form.getInputByValue("百度一下");
// 得到搜索框
final HtmlTextInput textField = form.getInputByName("q1");
//搜索我的id
textField.setValueAttribute("th是个小屁孩");
// 输入好了,我们点一下这个按钮
final HtmlPage nextPage = button.click();
// 我把结果转成String
String result = nextPage.asXml();
System.out.println(result); //得到的是点击后的网页
感觉httpunit比httpclient简单多了。 Java爬虫以后可以多尝试这个框架。提取节点的方法有很多,可以直接调用,但是好像不能从div的类中提取节点,但是可以根据id抓取。获取节点,唉,如果 div 没有写入 id,我不知道如何获取 网站。好像没有这样的方法可以按类来抓取。懂的同学可以给点思路。 查看全部
htmlunit抓取动态网页(没写代码实现获取网页源代码代码模拟按钮的方法)
1.几行代码即可获取网页源代码。
final WebClient webClient=new WebClient();
final HtmlPage page=webClient.getPage("http://www.baidu.com");
System.out.println(page.asText()); //asText()是以文本格式显示
System.out.println(page.asXml()); //asXml()是以xml格式显示
webClient.closeAllWindows();
2.模拟文本框和模拟按钮提交,我们来模拟模拟百度搜索关键字的实现。
// 得到浏览器对象,直接New一个就能得到,现在就好比说你得到了一个浏览器了
WebClient webclient = new WebClient();
// 这里是配置一下不加载css和javaScript,因为httpunit对javascript兼容性不太好
webclient.getOptions().setCssEnabled(false);
webclient.getOptions().setJavaScriptEnabled(false);
// 做的第一件事,去拿到这个网页,只需要调用getPage这个方法即可
HtmlPage htmlpage = webclient.getPage("http://baidu.com");
// 根据名字得到一个表单,查看上面这个网页的源代码可以发现表单的名字叫“f”
final HtmlForm form = htmlpage.getFormByName("f");
// 同样道理,获取”百度一下“这个按钮
final HtmlSubmitInput button = form.getInputByValue("百度一下");
// 得到搜索框
final HtmlTextInput textField = form.getInputByName("q1");
//搜索我的id
textField.setValueAttribute("th是个小屁孩");
// 输入好了,我们点一下这个按钮
final HtmlPage nextPage = button.click();
// 我把结果转成String
String result = nextPage.asXml();
System.out.println(result); //得到的是点击后的网页
感觉httpunit比httpclient简单多了。 Java爬虫以后可以多尝试这个框架。提取节点的方法有很多,可以直接调用,但是好像不能从div的类中提取节点,但是可以根据id抓取。获取节点,唉,如果 div 没有写入 id,我不知道如何获取 网站。好像没有这样的方法可以按类来抓取。懂的同学可以给点思路。
htmlunit抓取动态网页(一个百度动态页面SEO优化动态网页的办法和内容有哪些)
网站优化 • 优采云 发表了文章 • 0 个评论 • 56 次浏览 • 2022-01-25 11:03
企业要想做好网站网络推广,就需要了解搜索引擎的爬取规则,做好百度动态页面SEO。相信大家都知道搜索引擎抓取动态页面的难度。让成长超人的小编来给我们讲解一下如何优化动态页面。
1. 设置静态导入
在“动静结合、静制动”的原则指导下,可以对网站进行一些修正,尽可能提高动态网页在搜索引擎中的可见度。网络实现方法,例如将动态网页编译成静态主页或站点地图的链接,在静态目录中显示动态页面。也许为动态页面创建一个特殊的静态导入页面,链接到动态页面,并将静态导入页面提交给搜索引擎。
2. 付费登录搜索引擎
对于动态的网站,它由内容管理系统发布并连接到整个网站 数据库。在线推广的直接方式是登录并付费。提倡将动态网页直接提交到搜索引擎目录或者做关键词广告,保证网站被搜索。
3.改进的搜索引擎支持
搜索引擎一直在改进对动态页面的支持,但是这些搜索引擎在抓取动态页面时,为了防止搜索机器人的陷阱,搜索引擎只抓取动态页面和链接到静态页面的动态页面链接。不再抓取动态页面,这意味着不会对动态页面中的链接进行深入访问。
相信我们对成长超人为我们编写的SEO优化动态页面的方法和内容有一定的了解。事实上,修订并不适合所有人。您可以获得更多 SEO 优化的内容。看看这个网站上的其他网络推广技巧和经验,相信你会收获不少。 查看全部
htmlunit抓取动态网页(一个百度动态页面SEO优化动态网页的办法和内容有哪些)
企业要想做好网站网络推广,就需要了解搜索引擎的爬取规则,做好百度动态页面SEO。相信大家都知道搜索引擎抓取动态页面的难度。让成长超人的小编来给我们讲解一下如何优化动态页面。
1. 设置静态导入
在“动静结合、静制动”的原则指导下,可以对网站进行一些修正,尽可能提高动态网页在搜索引擎中的可见度。网络实现方法,例如将动态网页编译成静态主页或站点地图的链接,在静态目录中显示动态页面。也许为动态页面创建一个特殊的静态导入页面,链接到动态页面,并将静态导入页面提交给搜索引擎。
2. 付费登录搜索引擎
对于动态的网站,它由内容管理系统发布并连接到整个网站 数据库。在线推广的直接方式是登录并付费。提倡将动态网页直接提交到搜索引擎目录或者做关键词广告,保证网站被搜索。
3.改进的搜索引擎支持
搜索引擎一直在改进对动态页面的支持,但是这些搜索引擎在抓取动态页面时,为了防止搜索机器人的陷阱,搜索引擎只抓取动态页面和链接到静态页面的动态页面链接。不再抓取动态页面,这意味着不会对动态页面中的链接进行深入访问。
相信我们对成长超人为我们编写的SEO优化动态页面的方法和内容有一定的了解。事实上,修订并不适合所有人。您可以获得更多 SEO 优化的内容。看看这个网站上的其他网络推广技巧和经验,相信你会收获不少。
htmlunit抓取动态网页(PythonJavaScript:如何利用Webkit从从渲染网页中获取数据)
网站优化 • 优采云 发表了文章 • 0 个评论 • 45 次浏览 • 2022-01-25 10:19
原来的
主题 Python JavaScript
当我们进行网络爬取时,我们会使用一定的规则从返回的 HTML 数据中提取有效信息。但是如果网页收录 JavaScript 代码,我们必须渲染它以获取原创数据。在这一点上,如果我们仍然以通常的方式从中抓取数据,我们将一无所获。浏览器知道如何处理这段代码并显示出来,但是我们的程序应该如何处理这段代码呢?接下来,我将介绍一种简单粗暴的方法来抓取收录 JavaScript 代码的网页信息。
大多数人使用 lxml 和 BeautifulSoup 这两个包来提取数据。在这篇文章中我不会涉及任何爬虫框架的内容,因为我只使用了最基本的 lxml 包来处理数据。你可能想知道为什么我更喜欢 lxml。那是因为lxml使用元素遍历来处理数据,而不是像BeautifulSoup那样使用正则表达式来提取数据。在这篇文章中我要介绍一个非常有趣的案例——突然发现我的文章出现在最近的Pycoders周刊第147期,所以我想爬取Pycoders周刊中所有档案的链接。
显然,这是一个带有 JavaScript 渲染的网页。我想抓取网页中的所有个人资料信息和相应的链接信息。那么我该怎么办呢?首先,我们无法通过 HTTP 方法获取任何信息。
1import requests
2from lxml import html
3
4# storing response
5response = requests.get('http://pycoders.com/archive')
6# creating lxml tree from response body
7tree = html.fromstring(response.text)
8
9# Finding all anchor tags in response
10print tree.xpath('//div[@class="campaign"]/a/@href')
11
12
当我们运行上述代码时,我们无法获得任何信息。这怎么可能?网页清楚地显示了这么多文件的信息。接下来我们需要考虑如何解决这个问题?
如何获取内容信息?
接下来我将展示如何使用 Web 工具包从 JS 渲染的网页中获取数据。什么是网络套件?Web 工具包可以做任何浏览器可以处理的事情。对于某些浏览器,Web kit 是底层的网页渲染工具。Web kit 是 QT 库的一部分,所以如果你已经安装了 QT 和 PyQT4 库,你可以直接运行它。
您可以使用命令行安装存储库:
1sudo apt-get install python-qt4
2
3
现在所有的准备工作都完成了,我们将使用一种全新的方法来提取信息。
解决方案
我们首先通过 Web kit 发送请求信息,然后等待页面完全加载,然后将其分配给变量。接下来我们使用 lxml 从 HTML 数据中提取有效信息。这个过程需要一点时间,但您会惊讶地看到整个页面加载完毕。
1import sys
2from PyQt4.QtGui import *
3from PyQt4.Qtcore import *
4from PyQt4.QtWebKit import *
5
6class Render(QWebPage):
7 def __init__(self, url):
8 self.app = QApplication(sys.argv)
9 QWebPage.__init__(self)
10 self.loadFinished.connect(self._loadFinished)
11 self.mainFrame().load(QUrl(url))
12 self.app.exec_()
13
14 def _loadFinished(self, result):
15 self.frame = self.mainFrame()
16 self.app.quit()
17
18
Render 类可用于渲染网页。当我们创建一个新的 Render 类时,它可以加载 url 中的所有信息并将其存储在一个新的框架中。
使用上面的代码,我们将 HTML 结果存储在变量 result 中。由于lxml不能直接处理这种特殊的字符串数据,我们需要转换数据格式。
1# QString should be converted to string before processed by lxml
2formatted_result = str(result.toAscii())
3
4# Next build lxml tree from formatted_result
5tree = html.fromstring(formatted_result)
6
7# Now using correct Xpath we are fetching URL of archives
8archive_links = tree.xpath('//div[@class="campaign"]/a/@href')
9print archive_links
10
11
使用上面的代码,我们可以得到所有的文件链接信息,然后我们可以使用这些Render和这些URL链接来提取文本内容信息。Web kit 提供了一个强大的网页渲染工具,我们可以使用这个工具从 JS 渲染的网页中抓取有效的信息。
在本文中,我介绍了一种从 JS 渲染的网页中获取信息的有效方法。虽然这个工具比较慢,但是非常简单粗暴。我希望你会喜欢这个文章。现在您可以将此方法应用于您发现难以处理的任何网页。
愿你事事如意。
原文链接: 查看全部
htmlunit抓取动态网页(PythonJavaScript:如何利用Webkit从从渲染网页中获取数据)
原来的
主题 Python JavaScript
当我们进行网络爬取时,我们会使用一定的规则从返回的 HTML 数据中提取有效信息。但是如果网页收录 JavaScript 代码,我们必须渲染它以获取原创数据。在这一点上,如果我们仍然以通常的方式从中抓取数据,我们将一无所获。浏览器知道如何处理这段代码并显示出来,但是我们的程序应该如何处理这段代码呢?接下来,我将介绍一种简单粗暴的方法来抓取收录 JavaScript 代码的网页信息。
大多数人使用 lxml 和 BeautifulSoup 这两个包来提取数据。在这篇文章中我不会涉及任何爬虫框架的内容,因为我只使用了最基本的 lxml 包来处理数据。你可能想知道为什么我更喜欢 lxml。那是因为lxml使用元素遍历来处理数据,而不是像BeautifulSoup那样使用正则表达式来提取数据。在这篇文章中我要介绍一个非常有趣的案例——突然发现我的文章出现在最近的Pycoders周刊第147期,所以我想爬取Pycoders周刊中所有档案的链接。
显然,这是一个带有 JavaScript 渲染的网页。我想抓取网页中的所有个人资料信息和相应的链接信息。那么我该怎么办呢?首先,我们无法通过 HTTP 方法获取任何信息。
1import requests
2from lxml import html
3
4# storing response
5response = requests.get('http://pycoders.com/archive')
6# creating lxml tree from response body
7tree = html.fromstring(response.text)
8
9# Finding all anchor tags in response
10print tree.xpath('//div[@class="campaign"]/a/@href')
11
12
当我们运行上述代码时,我们无法获得任何信息。这怎么可能?网页清楚地显示了这么多文件的信息。接下来我们需要考虑如何解决这个问题?
如何获取内容信息?
接下来我将展示如何使用 Web 工具包从 JS 渲染的网页中获取数据。什么是网络套件?Web 工具包可以做任何浏览器可以处理的事情。对于某些浏览器,Web kit 是底层的网页渲染工具。Web kit 是 QT 库的一部分,所以如果你已经安装了 QT 和 PyQT4 库,你可以直接运行它。
您可以使用命令行安装存储库:
1sudo apt-get install python-qt4
2
3
现在所有的准备工作都完成了,我们将使用一种全新的方法来提取信息。
解决方案
我们首先通过 Web kit 发送请求信息,然后等待页面完全加载,然后将其分配给变量。接下来我们使用 lxml 从 HTML 数据中提取有效信息。这个过程需要一点时间,但您会惊讶地看到整个页面加载完毕。
1import sys
2from PyQt4.QtGui import *
3from PyQt4.Qtcore import *
4from PyQt4.QtWebKit import *
5
6class Render(QWebPage):
7 def __init__(self, url):
8 self.app = QApplication(sys.argv)
9 QWebPage.__init__(self)
10 self.loadFinished.connect(self._loadFinished)
11 self.mainFrame().load(QUrl(url))
12 self.app.exec_()
13
14 def _loadFinished(self, result):
15 self.frame = self.mainFrame()
16 self.app.quit()
17
18
Render 类可用于渲染网页。当我们创建一个新的 Render 类时,它可以加载 url 中的所有信息并将其存储在一个新的框架中。
使用上面的代码,我们将 HTML 结果存储在变量 result 中。由于lxml不能直接处理这种特殊的字符串数据,我们需要转换数据格式。
1# QString should be converted to string before processed by lxml
2formatted_result = str(result.toAscii())
3
4# Next build lxml tree from formatted_result
5tree = html.fromstring(formatted_result)
6
7# Now using correct Xpath we are fetching URL of archives
8archive_links = tree.xpath('//div[@class="campaign"]/a/@href')
9print archive_links
10
11
使用上面的代码,我们可以得到所有的文件链接信息,然后我们可以使用这些Render和这些URL链接来提取文本内容信息。Web kit 提供了一个强大的网页渲染工具,我们可以使用这个工具从 JS 渲染的网页中抓取有效的信息。
在本文中,我介绍了一种从 JS 渲染的网页中获取信息的有效方法。虽然这个工具比较慢,但是非常简单粗暴。我希望你会喜欢这个文章。现在您可以将此方法应用于您发现难以处理的任何网页。
愿你事事如意。
原文链接:
htmlunit抓取动态网页(就是怎么用htmlunit爬虫工具来爬取京东页面下该类目下)
网站优化 • 优采云 发表了文章 • 0 个评论 • 46 次浏览 • 2022-01-24 18:07
由于是第一次使用爬虫爬取网页内容,对于一些特殊情况我不是很擅长处理。在这里,我将与您分享我遇到的一些情况。
public static String getPage(String s_url, String charset) {
if (s_url == null) {
return null;
}
try {
URL url = new URL(s_url);
BufferedReader bReader = new BufferedReader(new InputStreamReader(url.openStream(), charset));
String s;
StringBuffer sBuffer = new StringBuffer();
while ((s=bReader.readLine())!=null) {
sBuffer = sBuffer.append(s);
}
url = null;
return sBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
上面的代码应该是最简单的获取网页源代码的方法了。您可以通过网页的url和编码方式直接获取网页的源代码,从而获得您想要的信息。但事情并不总是像想象的那么简单。目前的情况是这样的。我需要爬取的页面是京东三级分类下的商品信息。这种编码的结果都是乱码。后来在访问地址后面加上了?enc=utf-8,得到的页面终于没有乱码了,但是京东页面返回的结果却是“No product found”,真是心碎。如果大神知道如何解决这个问题,请告诉我。
好了,废话就说到这里,下面是如何使用htmlunit爬虫工具爬取京东页面
System.out.println("开始爬取页面了...");
//创建一个webclient
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setTimeout(10000);
try{
//获取页面
HtmlPage page = webClient.getPage("http://list.jd.com/list.html?cat=1620,1621,1627");
List divs = page.getByXPath("//div[@id='plist']");
HtmlDivision div = (HtmlDivision)divs.get(0);
HtmlUnorderedList ul = (HtmlUnorderedList)div.getFirstChild();
List lis = ul.getHtmlElementsByTagName("li");
for(int i = 0; i < lis.size(); i ++){
HtmlListItem li = lis.get(i);
String index = li.getAttribute("index");
if(index == null || "".equals(index))
continue;
//打印出页面中的商品所对应的skuid
System.out.println("第" + li.getAttribute("index") + "个商品的skuid=" + li.getAttribute("data-sku"));
}
//获取该类目下的商品总页数
List divs2 = page.getByXPath("//div[@id='J_bottomPage']");
HtmlDivision div2 = (HtmlDivision)divs2.get(0);
List b = div2.getHtmlElementsByTagName("b");
for(int i = 0; i < b.size(); i++){
String classname = b.get(i).getAttribute("class");
if(classname != null && !"".equals(classname)){
continue;
}
String pagetotal = b.get(i).getFirstChild().toString();
System.out.println("总页数为" + pagetotal);
}
System.out.println("哈哈");
}catch(Exception e){
e.printStackTrace();
}finally{
//关闭webclient
webClient.closeAllWindows();
}
如上,可以得到京东页面上该分类下所有产品的skuid和总页数。下一个问题很好解决~
htmlunit相关jar包下载地址: 查看全部
htmlunit抓取动态网页(就是怎么用htmlunit爬虫工具来爬取京东页面下该类目下)
由于是第一次使用爬虫爬取网页内容,对于一些特殊情况我不是很擅长处理。在这里,我将与您分享我遇到的一些情况。
public static String getPage(String s_url, String charset) {
if (s_url == null) {
return null;
}
try {
URL url = new URL(s_url);
BufferedReader bReader = new BufferedReader(new InputStreamReader(url.openStream(), charset));
String s;
StringBuffer sBuffer = new StringBuffer();
while ((s=bReader.readLine())!=null) {
sBuffer = sBuffer.append(s);
}
url = null;
return sBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
上面的代码应该是最简单的获取网页源代码的方法了。您可以通过网页的url和编码方式直接获取网页的源代码,从而获得您想要的信息。但事情并不总是像想象的那么简单。目前的情况是这样的。我需要爬取的页面是京东三级分类下的商品信息。这种编码的结果都是乱码。后来在访问地址后面加上了?enc=utf-8,得到的页面终于没有乱码了,但是京东页面返回的结果却是“No product found”,真是心碎。如果大神知道如何解决这个问题,请告诉我。
好了,废话就说到这里,下面是如何使用htmlunit爬虫工具爬取京东页面
System.out.println("开始爬取页面了...");
//创建一个webclient
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setTimeout(10000);
try{
//获取页面
HtmlPage page = webClient.getPage("http://list.jd.com/list.html?cat=1620,1621,1627");
List divs = page.getByXPath("//div[@id='plist']");
HtmlDivision div = (HtmlDivision)divs.get(0);
HtmlUnorderedList ul = (HtmlUnorderedList)div.getFirstChild();
List lis = ul.getHtmlElementsByTagName("li");
for(int i = 0; i < lis.size(); i ++){
HtmlListItem li = lis.get(i);
String index = li.getAttribute("index");
if(index == null || "".equals(index))
continue;
//打印出页面中的商品所对应的skuid
System.out.println("第" + li.getAttribute("index") + "个商品的skuid=" + li.getAttribute("data-sku"));
}
//获取该类目下的商品总页数
List divs2 = page.getByXPath("//div[@id='J_bottomPage']");
HtmlDivision div2 = (HtmlDivision)divs2.get(0);
List b = div2.getHtmlElementsByTagName("b");
for(int i = 0; i < b.size(); i++){
String classname = b.get(i).getAttribute("class");
if(classname != null && !"".equals(classname)){
continue;
}
String pagetotal = b.get(i).getFirstChild().toString();
System.out.println("总页数为" + pagetotal);
}
System.out.println("哈哈");
}catch(Exception e){
e.printStackTrace();
}finally{
//关闭webclient
webClient.closeAllWindows();
}
如上,可以得到京东页面上该分类下所有产品的skuid和总页数。下一个问题很好解决~
htmlunit相关jar包下载地址:
htmlunit抓取动态网页(1.HtmlUnit的学习方法是什么?怎么样?HtmlUnit)
网站优化 • 优采云 发表了文章 • 0 个评论 • 52 次浏览 • 2022-01-23 05:07
1.HtmlUnit 是一个用java 编写的无界面浏览器,它可以模拟html 文档、通过API 调用页面、填写表单、点击链接等等。像普通浏览器一样运行。通常用于测试和从网页中抓取信息。而HtmlUnit有HttpClient和soup的功能,但是速度比较慢,但是如果取消它解析css和js的功能,速度也会有所提升,默认开启。
2.这里,HtmlUnit是用来爬取数据的,主要是为了获取他的js和css。
3.主要代码如下
package com.los;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.los.util.DownlandPic;
import java.io.IOException;
import java.util.regex.Pattern;
public class HtmlUnitTest {
public static void main(String[] args) throws IOException {
DownlandPic dd = new DownlandPic();
WebClient webClient = new WebClient();//实例化web客户端
//http://www.bdqn.cn/ https://www.baidu.com/?tn=78000241_22_hao_pg
String url = "http://www.bdqn.cn/";
HtmlPage page = webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000); //等侍js脚本执行完成
System.out.println(page.asXml());
DomNodeList img = page.getElementsByTagName("script");
for (int i=0;i 0) {
output.write(buffer, 0, length);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static int getCharacterPosition3(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 2){
break;
}
}
return slashMatcher.start();
}
public static int getCharacterPosition4(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 3){
break;
}
}
return slashMatcher.start();
}
public static void main(String[] args) {
String content = "<img class=\"lazy\" data-original=\"/img/newImg/news_img2.jpg\" src=\"/img/newImg/news2.jpg\" style=\"display: block;\"/>";
System.out.println(getCharacterPosition3(content));
System.out.println(getCharacterPosition4(content));
String substring = content.substring(getCharacterPosition3(content), getCharacterPosition4(content));
System.out.println(substring);
}
}
3.因为这里网页中的图片地址是相对路径,所以在下载的时候到页面中找到它的绝对路径,拼接在下载地址中。下载的路径必须与图片标签中的地址对应爬取后存储在本地页面,否则无法找到。
3.之所以在匹配“时写2和3是根据这里爬取的数据。
4.相对于其他爬取网页的写法,这个可能更简单,但是更能体现效果。如有错误请多多指教。至于页面不会显示,涉及隐私。
5.了解HtmlUnit请参考:地址 查看全部
htmlunit抓取动态网页(1.HtmlUnit的学习方法是什么?怎么样?HtmlUnit)
1.HtmlUnit 是一个用java 编写的无界面浏览器,它可以模拟html 文档、通过API 调用页面、填写表单、点击链接等等。像普通浏览器一样运行。通常用于测试和从网页中抓取信息。而HtmlUnit有HttpClient和soup的功能,但是速度比较慢,但是如果取消它解析css和js的功能,速度也会有所提升,默认开启。
2.这里,HtmlUnit是用来爬取数据的,主要是为了获取他的js和css。
3.主要代码如下
package com.los;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.los.util.DownlandPic;
import java.io.IOException;
import java.util.regex.Pattern;
public class HtmlUnitTest {
public static void main(String[] args) throws IOException {
DownlandPic dd = new DownlandPic();
WebClient webClient = new WebClient();//实例化web客户端
//http://www.bdqn.cn/ https://www.baidu.com/?tn=78000241_22_hao_pg
String url = "http://www.bdqn.cn/";
HtmlPage page = webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000); //等侍js脚本执行完成
System.out.println(page.asXml());
DomNodeList img = page.getElementsByTagName("script");
for (int i=0;i 0) {
output.write(buffer, 0, length);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static int getCharacterPosition3(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 2){
break;
}
}
return slashMatcher.start();
}
public static int getCharacterPosition4(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 3){
break;
}
}
return slashMatcher.start();
}
public static void main(String[] args) {
String content = "<img class=\"lazy\" data-original=\"/img/newImg/news_img2.jpg\" src=\"/img/newImg/news2.jpg\" style=\"display: block;\"/>";
System.out.println(getCharacterPosition3(content));
System.out.println(getCharacterPosition4(content));
String substring = content.substring(getCharacterPosition3(content), getCharacterPosition4(content));
System.out.println(substring);
}
}
3.因为这里网页中的图片地址是相对路径,所以在下载的时候到页面中找到它的绝对路径,拼接在下载地址中。下载的路径必须与图片标签中的地址对应爬取后存储在本地页面,否则无法找到。
3.之所以在匹配“时写2和3是根据这里爬取的数据。

4.相对于其他爬取网页的写法,这个可能更简单,但是更能体现效果。如有错误请多多指教。至于页面不会显示,涉及隐私。
5.了解HtmlUnit请参考:地址
htmlunit抓取动态网页(搜狗微信公众号更新公告(2015.03.23) )
网站优化 • 优采云 发表了文章 • 0 个评论 • 53 次浏览 • 2022-01-23 05:04
)
最后更新于 2018.1.3
只为自己留个记录
要添加的功能:
1.获取历史中的所有消息
2. 爬取10多条数据
3.公众号信息自定义抓取
下面以搜狗微信公众号搜索微信公众号为例!
搜狗微信公众号作为分析入口:[此处填写公众号]&ie=utf8&sug=n&sug_type=
DEMO 中的完整 URL 为:%E6%AF%8F%E6%97%A5%E8%8A%82%E5%A5%8F&ie=utf8&sug=n&sug_type=
package cc.buckler.test;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Test;
import java.io.IOException;
public class TestData {
private String ENTRY_URL = "http://weixin.sogou.com/weixin ... %3B//入口地址
private String QUERY_WORD = "DOTA每日节奏";//查询参数
private String BASE_URL = "";//从入口进入公众号后的公众号地址
private String WE_CHAT_URL = "http://mp.weixin.qq.com";//微信公众号官方入口
private int NEW_MSG_ID = 0;//最新msgId
private int MSG_NUM = 20;//需要获取的数量
@Test
public void getData() {
String url = String.format(ENTRY_URL, QUERY_WORD);
//System.out.println(url);
WebClient webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setRedirectEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setTimeout(50000);
Document doc = null;
try {
//首先用jsoup获取搜狗入口公众号连接
doc = Jsoup.connect(url).get();
//System.out.println("doc:" + doc);
BASE_URL = doc.select("p a").attr("href");
//System.out.println(BASE_URL);
//使用htmlunit加载公众号文章列表
HtmlPage htmlPage = webClient.getPage(BASE_URL);
webClient.waitForBackgroundJavaScript(10000);
doc = Jsoup.parse(htmlPage.asXml());
//System.out.println("doc:" + doc);
//获取最新文章msgid,之后的循环用msgid-1
String lastMsgId = doc.select(".weui_media_box").attr("msgid");
NEW_MSG_ID = Integer.parseInt(lastMsgId);
//System.out.println(NEW_MSG_ID);
for (int i = NEW_MSG_ID; i >= NEW_MSG_ID - MSG_NUM; i--) {
String articalPrev = "#WXAPPMSG";
String articalId = articalPrev + i;
String h4 = articalId + " h4";
String weui_media_desc = articalId + " .weui_media_desc";
String weui_media_extra_info = articalId + " .weui_media_extra_info";
System.out.println(articalId);
String title = doc.select(h4).text();
System.out.println(title);
String detailUrl = doc.select(h4).attr("hrefs");//2018.1.3 ok
System.out.println(WE_CHAT_URL + detailUrl);
String note = doc.select(weui_media_desc).text();//2018.1.3 ok
if (note.compareToIgnoreCase("") == 0) {
continue;
}
System.out.println(note);
String releaseDate = doc.select(weui_media_extra_info).text().toString();//2018.1.3 ok
if (releaseDate.compareToIgnoreCase("") == 0) {
continue;
}
System.out.println(releaseDate);
}
webClient.close();
} catch (IOException e) {
e.printStackTrace();
webClient.close();
}
}
} 查看全部
htmlunit抓取动态网页(搜狗微信公众号更新公告(2015.03.23)
)
最后更新于 2018.1.3
只为自己留个记录
要添加的功能:
1.获取历史中的所有消息
2. 爬取10多条数据
3.公众号信息自定义抓取
下面以搜狗微信公众号搜索微信公众号为例!
搜狗微信公众号作为分析入口:[此处填写公众号]&ie=utf8&sug=n&sug_type=
DEMO 中的完整 URL 为:%E6%AF%8F%E6%97%A5%E8%8A%82%E5%A5%8F&ie=utf8&sug=n&sug_type=
package cc.buckler.test;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Test;
import java.io.IOException;
public class TestData {
private String ENTRY_URL = "http://weixin.sogou.com/weixin ... %3B//入口地址
private String QUERY_WORD = "DOTA每日节奏";//查询参数
private String BASE_URL = "";//从入口进入公众号后的公众号地址
private String WE_CHAT_URL = "http://mp.weixin.qq.com";//微信公众号官方入口
private int NEW_MSG_ID = 0;//最新msgId
private int MSG_NUM = 20;//需要获取的数量
@Test
public void getData() {
String url = String.format(ENTRY_URL, QUERY_WORD);
//System.out.println(url);
WebClient webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setRedirectEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setTimeout(50000);
Document doc = null;
try {
//首先用jsoup获取搜狗入口公众号连接
doc = Jsoup.connect(url).get();
//System.out.println("doc:" + doc);
BASE_URL = doc.select("p a").attr("href");
//System.out.println(BASE_URL);
//使用htmlunit加载公众号文章列表
HtmlPage htmlPage = webClient.getPage(BASE_URL);
webClient.waitForBackgroundJavaScript(10000);
doc = Jsoup.parse(htmlPage.asXml());
//System.out.println("doc:" + doc);
//获取最新文章msgid,之后的循环用msgid-1
String lastMsgId = doc.select(".weui_media_box").attr("msgid");
NEW_MSG_ID = Integer.parseInt(lastMsgId);
//System.out.println(NEW_MSG_ID);
for (int i = NEW_MSG_ID; i >= NEW_MSG_ID - MSG_NUM; i--) {
String articalPrev = "#WXAPPMSG";
String articalId = articalPrev + i;
String h4 = articalId + " h4";
String weui_media_desc = articalId + " .weui_media_desc";
String weui_media_extra_info = articalId + " .weui_media_extra_info";
System.out.println(articalId);
String title = doc.select(h4).text();
System.out.println(title);
String detailUrl = doc.select(h4).attr("hrefs");//2018.1.3 ok
System.out.println(WE_CHAT_URL + detailUrl);
String note = doc.select(weui_media_desc).text();//2018.1.3 ok
if (note.compareToIgnoreCase("") == 0) {
continue;
}
System.out.println(note);
String releaseDate = doc.select(weui_media_extra_info).text().toString();//2018.1.3 ok
if (releaseDate.compareToIgnoreCase("") == 0) {
continue;
}
System.out.println(releaseDate);
}
webClient.close();
} catch (IOException e) {
e.printStackTrace();
webClient.close();
}
}
}
htmlunit抓取动态网页(.xmlmaven依赖代码 )
网站优化 • 优采云 发表了文章 • 0 个评论 • 72 次浏览 • 2022-01-22 17:12
)
今天用jsoup做爬虫的时候发现jsoup只能爬静态页面,对ajax和json动态生成页面的支持不友好。
所以我尝试直接将param和data header随请求一起发送,希望直接返回json数据,但是可能因为网站接口不支持而无法成功。
尝试了其他方法后,从网上发现可以用htmlunit模拟浏览器,生成动态网页,然后用jsoup解析生成的动态网页
以下是pom.xml maven依赖代码
以下是java代码
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.io.IOException;
public class JsoupTest {
public static void main(String[] args) {
queryDocument("北斗");
}
public static void queryDocument(String documentName){
WebClient browser = new WebClient();
browser.getOptions().setCssEnabled(false);
browser.getOptions().setJavaScriptEnabled(true);
browser.getOptions().setThrowExceptionOnScriptError(false);
String url = "http://oar.nstl.gov.cn/Paper/S ... 3B%3B
try {
HtmlPage htmlPage = browser.getPage(url);
browser.waitForBackgroundJavaScript(3000);
Document document = Jsoup.parse(htmlPage.asXml());
Element paper = document.getElementById("paper");
System.out.println(paper);
} catch (IOException e) {
e.printStackTrace();
}
}
} 查看全部
htmlunit抓取动态网页(.xmlmaven依赖代码
)
今天用jsoup做爬虫的时候发现jsoup只能爬静态页面,对ajax和json动态生成页面的支持不友好。
所以我尝试直接将param和data header随请求一起发送,希望直接返回json数据,但是可能因为网站接口不支持而无法成功。
尝试了其他方法后,从网上发现可以用htmlunit模拟浏览器,生成动态网页,然后用jsoup解析生成的动态网页
以下是pom.xml maven依赖代码
以下是java代码
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.io.IOException;
public class JsoupTest {
public static void main(String[] args) {
queryDocument("北斗");
}
public static void queryDocument(String documentName){
WebClient browser = new WebClient();
browser.getOptions().setCssEnabled(false);
browser.getOptions().setJavaScriptEnabled(true);
browser.getOptions().setThrowExceptionOnScriptError(false);
String url = "http://oar.nstl.gov.cn/Paper/S ... 3B%3B
try {
HtmlPage htmlPage = browser.getPage(url);
browser.waitForBackgroundJavaScript(3000);
Document document = Jsoup.parse(htmlPage.asXml());
Element paper = document.getElementById("paper");
System.out.println(paper);
} catch (IOException e) {
e.printStackTrace();
}
}
}
htmlunit抓取动态网页(【K线形态】模拟点击颜色分类,然后读取定价参考(1))
网站优化 • 优采云 发表了文章 • 0 个评论 • 63 次浏览 • 2022-01-22 01:23
通过交互式网络抓取获取天猫商品价格。
方法:模拟点击颜色分类,然后读取定价
参考(1):
主要利用CasperJS工具包:
最重要的是使用css3选择器来选择需要操作的网页的DOM元素。对于 css3 选择器,请参见:
查看元素的提示:
在浏览器上,右键点击对应元素,选择“Inspect Element”,查看对应元素的html代码。
选择器测试提示:
IE或firefox,F12打开开发者窗口,在搜索栏中输入选择器检测选择器效果。
IE:
火狐:
以下代码使用 casperjs tm.js 运行:
var casper = require('casper').create({
clientScripts: ["jquery-1.8.0.js"],
verbose: false,
logLevel: 'debug',
pageSettings: {
loadImages: false, // The WebPage instance used by Casper will
loadPlugins: false // use these settings
}
});
phantom.outputEncoding = "gbk";//解决乱码问题
//获取需要采集的url列表
casper.start('http://detail.tmall.com/item.h ... 39%3B, function() {
console.log(this.getCurrentUrl());
//casper.GetDetailUrl(url);
});
//处理当前页面的所有sku价格与信息
casper.then(function getPic() {
product = casper.evaluate(function getProductFromPage() {
return $('ul[class*="tb-img"]').children().size();
});
console.log(product);
var str = ''
for (var i = 1; i li:nth-child(' + index + ') a');
return index;
};
casper.run();
以上代码参考(1)修改,只实现了给定链接的商品价格的抓取,并在控制台输出。如果要使用node.js抓取链接中的商品在多线程中列出,并通过json将捕获的价格发布到服务器,您可以参考原创方法。 查看全部
htmlunit抓取动态网页(【K线形态】模拟点击颜色分类,然后读取定价参考(1))
通过交互式网络抓取获取天猫商品价格。
方法:模拟点击颜色分类,然后读取定价
参考(1):
主要利用CasperJS工具包:
最重要的是使用css3选择器来选择需要操作的网页的DOM元素。对于 css3 选择器,请参见:
查看元素的提示:
在浏览器上,右键点击对应元素,选择“Inspect Element”,查看对应元素的html代码。
选择器测试提示:
IE或firefox,F12打开开发者窗口,在搜索栏中输入选择器检测选择器效果。
IE:
火狐:
以下代码使用 casperjs tm.js 运行:
var casper = require('casper').create({
clientScripts: ["jquery-1.8.0.js"],
verbose: false,
logLevel: 'debug',
pageSettings: {
loadImages: false, // The WebPage instance used by Casper will
loadPlugins: false // use these settings
}
});
phantom.outputEncoding = "gbk";//解决乱码问题
//获取需要采集的url列表
casper.start('http://detail.tmall.com/item.h ... 39%3B, function() {
console.log(this.getCurrentUrl());
//casper.GetDetailUrl(url);
});
//处理当前页面的所有sku价格与信息
casper.then(function getPic() {
product = casper.evaluate(function getProductFromPage() {
return $('ul[class*="tb-img"]').children().size();
});
console.log(product);
var str = ''
for (var i = 1; i li:nth-child(' + index + ') a');
return index;
};
casper.run();
以上代码参考(1)修改,只实现了给定链接的商品价格的抓取,并在控制台输出。如果要使用node.js抓取链接中的商品在多线程中列出,并通过json将捕获的价格发布到服务器,您可以参考原创方法。
htmlunit抓取动态网页(2019独角兽企业重金招聘Python工程师标准(gt;gt))
网站优化 • 优采云 发表了文章 • 0 个评论 • 57 次浏览 • 2022-01-22 01:18
2019独角兽企业招聘Python工程师标准>>>
最近在做一个项目的时候,有个需求:从一个网页抓取数据,需求是先抓取整个网页的html源码(用于以后的更新)。一开始看到这个简单,然后就匆忙打了代码(之前用的是Hadoop平台的分布式爬虫框架Nutch,用起来很方便,最后因为速度放弃了,但是生成的统计信息用于后续爬取),很快就成功下载了holder.html和finance.html页面,然后解析了holder.html页面后,解析了finance.html,然后很郁闷的在这个页面找到了我需要的东西. 数据不在 html 源代码中。去浏览器查看源码确实是这样的。源代码中确实没有我需要的数据。看来我的程序没有错。- 获取具有动态内容的 html 页面。
在号称国内最强的搜索引擎——百度上走了很久,我发现大部分人都在用WebDriver和HttpUnit(其实前者已经收录了后者)。我很高兴,终于找到了解决方案。. 如此兴奋地使用 WebDriver,我想诅咒。
以下是关于WebDriver的吐槽
WebDriver 是一个测试框架。本来不是为爬虫服务的,但我想说的是:八个字就差一步了,就不能更进一步吗?为什么网上那么多人推荐WebDriver?我觉得这些人不是从现实出发,甚至有人疯狂宣称WebDriver可以解析完成的页面,返回给那些想要爬取整个页面(包括动态生成的内容)的人。是的,WebDriver 可以完成这个任务,但是看到作者写的代码,我想说的是:哥们,你的代码太局限了,解析自己写的js代码,js代码简单,所以WebDriver当然可以毫无压力地完成任务。WebDriver解析动态内容时,取决于js代码的复杂性和多样性。
什么是复杂性?
粘贴一段代码
WebDriver driver = newInternetExplorerDriver ();
HtmlPage page = driver.get(url);
System.out.println(page.asXml());
这段代码的意思相信大家都能看懂。上面使用的IE内核,当然是FirefoxDriver、ChromeDriver、HtmlUnitDriver,使用这些驱动的原理是一样的,先打开浏览器(这需要时间),然后加载url并完成动态解析,然后就可以得到通过page.asXml()完成html页面,其中HtmlUnitDriver模拟无接口浏览器,java有引擎rhino执行js,HtmlUnitDriver使用rhino解析js。它将启动一个带有界面的浏览器,因此 HtmlUnitDriver 比前面三个要快。不管是什么驱动,都难免解析js,这需要时间,而且不同内核对js的支持方案也不一样。例如,HtmlUnitDriver 对带有滚动的 js 代码的支持很差,并且在执行过程中会报错。(亲身经历)。js代码的复杂性意味着不同内核支持的js并不完全相同。这个要根据具体情况来确定。好久没研究js了,就不说各个内核对js的支持了。
什么是多样性
前面说过,浏览器解析js是需要时间的。对于只嵌入少量js代码的页面,通过page.asXml()获取完整页面是没有问题的。但是对于内嵌js代码较多的页面,解析js需要花费很多时间(对于jvm),那么通过page.asXml()获取的页面大部分时间不收录动态生成的内容。的。问题是,为什么说WebDriver可以获取动态内容的html页面呢?网上有人说在driver.get(url)之后,当前线程需要等待一段时间才能拿到完成的页面,类似下面的形式
WebDriver driver = new InternetExplorerDriver();
HtmlPage page = dirver.get(url);
Thread.sleep(2000);
System.output.println(page.asXml());
我根据这个想法尝试了以下,是的,它确实有效。但问题不就在那里吗?如何确定等待时间?类似于数据挖掘中确定阈值的经验方法?,或尽可能长。我觉得这些都不是很好的解决方案,时间成本也比较高。本来以为驱动解析js后应该可以捕获状态,于是就去找找找,但是根本没有这个方法,所以说WebDriver的设计者为什么不走一步forward,这样我们就可以程序获取驱动解析js完成后的状态,所以不需要使用Thread.sleep(2000)等不确定的代码,可惜找不到,真是让我心痛。场。FirefoxDriver,ChromeDriver,HtmlUnitDriver 也有同样的问题。可以说,使用WebDriver辅助爬取到动态生成的网页得到的结果是非常不稳定的。我对此有深刻的理解。在使用IEDriver的时候,同一个页面两次爬取的结果会不一样,有时候IE甚至会直接挂掉。你敢在爬虫程序中使用这样的东西吗?我不敢。
另外,有人推荐使用 HttpUnit。其实WebDirver中的HtmlUnitDriver内部使用的是httpUnit,所以使用HttpUnit也会遇到同样的问题。我也做了一个实验,这是真的。通过Thread.sleep(2000)等待js解析完成,我觉得不可取。不确定性太大,尤其是在大规模爬取工作中。
综上所述,WebDriver 是一个为测试而设计的框架。虽然理论上可以用来辅助爬虫根据其原理获取收录动态内容的html页面,但在实际应用中并没有使用,不确定性太大。稳定性太差,速度太慢,让框架尽其所能吧,不要妥协自己的优势。
我的工作还没有完成,所以我继续上网寻找解决方案。这次找到了一个稳定的、高确定性的辅助工具——phantomjs。目前,我还没有完全理解这个东西。但目前已经用它来实现我想要的。在java中通过runtime.exec(arg)调用phantomjs获取解析js后的页面。我会发布代码
phantomjs端要执行的代码
system = require('system')
address = system.args[1];//获得命令行第二个参数 接下来会用到 //console.log('Loading a web page'); var page = require('webpage').create();
var url = address;
//console.log(url); page.open(url, function (status) {
//Page is loaded!
if (status !== 'success') {
console.log('Unable to post!');
} else {
//此处的打印,是将结果一流的形式output到java中,java通过InputStream可以获取该输出内容 console.log(page.content);
}
phantom.exit();
});
在java端执行的代码
public void getParseredHtml(){
String url = "www.bai.com";
Runtime runtime = Runtime.getRuntime();
runtime.exec("F:/phantomjs/phantomjs/phantomjs.exe F:/js/parser.js "+url);
InputStream in = runtime.getInputStream(); //后面的代码省略,得到了InputStream就好说了 }
这样就可以在java端获取解析后的html页面,而不是像Thread.sleep()这种不确定的代码,需要在WebDriver中使用才能获取可能完成的代码。需要说明一点:phantomjs端的js代码一定不能有语法错误,否则如果js代码编译不同,java端会一直等待,不会抛出异常。再者,使用phantomjs.exe时,java端每次都要开启一个phantomjs进程,耗费大量时间。但至少结果是稳定的。当然,最后我还没有使用phantomjs。我直接下载了自己需要的数据,并没有抓取整个页面,主要是速度问题(其实我对phantomjs不熟悉,所以不敢用,慎用)。
折腾了几天,虽然没有解决我的问题,但还是收获了很多知识。后期的工作就是熟悉phantomjs,看看能不能提高速度。如果能突破限速,以后爬网的时候就得心应手了。此外,Nutch 是框架。我很佩服我的伙伴们在使用它时的便利。后期有必要研究如何优化Nutch on Hadoop的爬取速度。此外,Nutch 原有的功能不会爬行。动态生成的页面内容,不过可以结合Nutch和WebDirver,说不定爬取的结果是稳定的,哈哈,这些只是想法,但是不试试怎么知道呢?
如果园丁对使用WebDriver辅助爬虫得到的结果的稳定性有什么想说的,不客气,因为我确实没有找到相关资料稳定爬取结果。 查看全部
htmlunit抓取动态网页(2019独角兽企业重金招聘Python工程师标准(gt;gt))
2019独角兽企业招聘Python工程师标准>>>

最近在做一个项目的时候,有个需求:从一个网页抓取数据,需求是先抓取整个网页的html源码(用于以后的更新)。一开始看到这个简单,然后就匆忙打了代码(之前用的是Hadoop平台的分布式爬虫框架Nutch,用起来很方便,最后因为速度放弃了,但是生成的统计信息用于后续爬取),很快就成功下载了holder.html和finance.html页面,然后解析了holder.html页面后,解析了finance.html,然后很郁闷的在这个页面找到了我需要的东西. 数据不在 html 源代码中。去浏览器查看源码确实是这样的。源代码中确实没有我需要的数据。看来我的程序没有错。- 获取具有动态内容的 html 页面。
在号称国内最强的搜索引擎——百度上走了很久,我发现大部分人都在用WebDriver和HttpUnit(其实前者已经收录了后者)。我很高兴,终于找到了解决方案。. 如此兴奋地使用 WebDriver,我想诅咒。

以下是关于WebDriver的吐槽
WebDriver 是一个测试框架。本来不是为爬虫服务的,但我想说的是:八个字就差一步了,就不能更进一步吗?为什么网上那么多人推荐WebDriver?我觉得这些人不是从现实出发,甚至有人疯狂宣称WebDriver可以解析完成的页面,返回给那些想要爬取整个页面(包括动态生成的内容)的人。是的,WebDriver 可以完成这个任务,但是看到作者写的代码,我想说的是:哥们,你的代码太局限了,解析自己写的js代码,js代码简单,所以WebDriver当然可以毫无压力地完成任务。WebDriver解析动态内容时,取决于js代码的复杂性和多样性。
什么是复杂性?
粘贴一段代码
WebDriver driver = newInternetExplorerDriver ();
HtmlPage page = driver.get(url);
System.out.println(page.asXml());
这段代码的意思相信大家都能看懂。上面使用的IE内核,当然是FirefoxDriver、ChromeDriver、HtmlUnitDriver,使用这些驱动的原理是一样的,先打开浏览器(这需要时间),然后加载url并完成动态解析,然后就可以得到通过page.asXml()完成html页面,其中HtmlUnitDriver模拟无接口浏览器,java有引擎rhino执行js,HtmlUnitDriver使用rhino解析js。它将启动一个带有界面的浏览器,因此 HtmlUnitDriver 比前面三个要快。不管是什么驱动,都难免解析js,这需要时间,而且不同内核对js的支持方案也不一样。例如,HtmlUnitDriver 对带有滚动的 js 代码的支持很差,并且在执行过程中会报错。(亲身经历)。js代码的复杂性意味着不同内核支持的js并不完全相同。这个要根据具体情况来确定。好久没研究js了,就不说各个内核对js的支持了。
什么是多样性
前面说过,浏览器解析js是需要时间的。对于只嵌入少量js代码的页面,通过page.asXml()获取完整页面是没有问题的。但是对于内嵌js代码较多的页面,解析js需要花费很多时间(对于jvm),那么通过page.asXml()获取的页面大部分时间不收录动态生成的内容。的。问题是,为什么说WebDriver可以获取动态内容的html页面呢?网上有人说在driver.get(url)之后,当前线程需要等待一段时间才能拿到完成的页面,类似下面的形式
WebDriver driver = new InternetExplorerDriver();
HtmlPage page = dirver.get(url);
Thread.sleep(2000);
System.output.println(page.asXml());
我根据这个想法尝试了以下,是的,它确实有效。但问题不就在那里吗?如何确定等待时间?类似于数据挖掘中确定阈值的经验方法?,或尽可能长。我觉得这些都不是很好的解决方案,时间成本也比较高。本来以为驱动解析js后应该可以捕获状态,于是就去找找找,但是根本没有这个方法,所以说WebDriver的设计者为什么不走一步forward,这样我们就可以程序获取驱动解析js完成后的状态,所以不需要使用Thread.sleep(2000)等不确定的代码,可惜找不到,真是让我心痛。场。FirefoxDriver,ChromeDriver,HtmlUnitDriver 也有同样的问题。可以说,使用WebDriver辅助爬取到动态生成的网页得到的结果是非常不稳定的。我对此有深刻的理解。在使用IEDriver的时候,同一个页面两次爬取的结果会不一样,有时候IE甚至会直接挂掉。你敢在爬虫程序中使用这样的东西吗?我不敢。
另外,有人推荐使用 HttpUnit。其实WebDirver中的HtmlUnitDriver内部使用的是httpUnit,所以使用HttpUnit也会遇到同样的问题。我也做了一个实验,这是真的。通过Thread.sleep(2000)等待js解析完成,我觉得不可取。不确定性太大,尤其是在大规模爬取工作中。
综上所述,WebDriver 是一个为测试而设计的框架。虽然理论上可以用来辅助爬虫根据其原理获取收录动态内容的html页面,但在实际应用中并没有使用,不确定性太大。稳定性太差,速度太慢,让框架尽其所能吧,不要妥协自己的优势。
我的工作还没有完成,所以我继续上网寻找解决方案。这次找到了一个稳定的、高确定性的辅助工具——phantomjs。目前,我还没有完全理解这个东西。但目前已经用它来实现我想要的。在java中通过runtime.exec(arg)调用phantomjs获取解析js后的页面。我会发布代码
phantomjs端要执行的代码

system = require('system')
address = system.args[1];//获得命令行第二个参数 接下来会用到 //console.log('Loading a web page'); var page = require('webpage').create();
var url = address;
//console.log(url); page.open(url, function (status) {
//Page is loaded!
if (status !== 'success') {
console.log('Unable to post!');
} else {
//此处的打印,是将结果一流的形式output到java中,java通过InputStream可以获取该输出内容 console.log(page.content);
}
phantom.exit();
});

在java端执行的代码

public void getParseredHtml(){
String url = "www.bai.com";
Runtime runtime = Runtime.getRuntime();
runtime.exec("F:/phantomjs/phantomjs/phantomjs.exe F:/js/parser.js "+url);
InputStream in = runtime.getInputStream(); //后面的代码省略,得到了InputStream就好说了 }

这样就可以在java端获取解析后的html页面,而不是像Thread.sleep()这种不确定的代码,需要在WebDriver中使用才能获取可能完成的代码。需要说明一点:phantomjs端的js代码一定不能有语法错误,否则如果js代码编译不同,java端会一直等待,不会抛出异常。再者,使用phantomjs.exe时,java端每次都要开启一个phantomjs进程,耗费大量时间。但至少结果是稳定的。当然,最后我还没有使用phantomjs。我直接下载了自己需要的数据,并没有抓取整个页面,主要是速度问题(其实我对phantomjs不熟悉,所以不敢用,慎用)。
折腾了几天,虽然没有解决我的问题,但还是收获了很多知识。后期的工作就是熟悉phantomjs,看看能不能提高速度。如果能突破限速,以后爬网的时候就得心应手了。此外,Nutch 是框架。我很佩服我的伙伴们在使用它时的便利。后期有必要研究如何优化Nutch on Hadoop的爬取速度。此外,Nutch 原有的功能不会爬行。动态生成的页面内容,不过可以结合Nutch和WebDirver,说不定爬取的结果是稳定的,哈哈,这些只是想法,但是不试试怎么知道呢?
如果园丁对使用WebDriver辅助爬虫得到的结果的稳定性有什么想说的,不客气,因为我确实没有找到相关资料稳定爬取结果。
htmlunit抓取动态网页(目录1.聚焦爬虫的发展在互联网金融领域应用)
网站优化 • 优采云 发表了文章 • 0 个评论 • 51 次浏览 • 2022-01-21 18:18
导读
马云说,大数据时代已经到来。现在有太多的互联网公司在做大数据,每个公司都有不止一个数据源。占很大比例的数据源之一是网络爬虫。但是,不同的公司有不同的业务背景,需要不同类型的数据。与用于搜索网站的通用爬虫不同,专注爬虫开始被越来越多的提及。
内容
1. 关注爬虫原理
2. 专注于爬虫的开发
3. 爬虫在互联网金融领域的应用
4. 结论
1.专注于爬虫的原理
1.1概念
聚焦爬虫,又称主题爬虫(或专业爬虫),是一种“针对特定主题”的网络爬虫。它与我们通常所说的爬虫(万能爬虫)的区别在于,聚焦爬虫在实现网络爬虫时需要进行主题筛选。它试图确保只抓取与主题相关的网页。
1.2 关注爬虫的分类
焦点爬虫主要分为两类。一种是浅焦点爬虫。所谓浅焦点爬虫,就是爬虫程序抓取特定网站的所有信息。它的工作方式和一般的爬虫几乎一样,唯一不同的是种子URL的选择决定了爬取内容的一致性,核心是种子URL的选择。另一种是深度聚焦爬虫。深度聚焦爬虫是指在大量不同内容的网页中,通过主题相关性算法,选择具有相似主题的URL和内容进行爬取。它的核心是如何判断抓取到的 URL 和页面内容是否与主题相关。
关系如下:
从图中可以看出,浅焦点爬虫可以看成是一种仅限于单一主题网站的通用爬虫,所以我们通常所说的焦点爬虫大多是指深度焦点爬虫。
1.2.1 浅焦点爬虫
浅焦点爬虫从一个或几个初始网页的URL开始,(例如分类信息网)获取初始网页上的URL,在抓取网页的过程中,不断地从原创网页中提取新的URL当前页面并将它们放入队列中,直到系统满意为止。某些停止条件。
其工作流程如下:
可以看出,浅焦点爬虫的基本原理和一般爬虫是一样的。使用主题网站可以保证爬取内容的主题一致。
1.2.2 深度关注爬行动物
Deep Focus Crawler 的主要特点是主题一致性。然而,在浩瀚的互联网大数据海洋中,要保证抓取到的数据的一致性并不是一件简单的事情。对于不同的数据需求,所需的策略和方法没有统一的答案。这里不谈具体的解决方案,只讨论常见的解决方案。
一、对于页面内容
这个解决方案是先爬取页面,不考虑页面的主题。对页面进行简单去噪后,使用主题提取策略提取处理后的页面内容的主题,最后对比设置的主题,如果主题一致,或者在一定的阈值内,则保存页面进行进一步的数据清洗。如果主题偏差超过阈值,则页面被简单地丢弃。
这种方法的优点是链接页面被完全覆盖,不会有数据遗漏。但缺点也很致命,那就是全覆盖页面,其中很大一部分是与主题无关的废弃页面,大大减慢了爬虫爬取数据的速度。到了后期,爬取数据的速度将是无法接受的。
二、对于 URL
上面介绍的浅焦点爬虫的核心是选择合适的种子URL。这些种子 URL 主要是主题 网站 的入口 URL。
网上的网站一般都有固定的主题,同一个网站中相同主题的页面的URL有一定的规律可循。由此,自然而然地产生了通过URL来预测页面主题的想法。另外,页面中的大部分超链接都有锚文本,锚文本基本上可以看作是对目标页面的概括描述。结合对URL的分析和对锚文本的分析,目标页面的话题预测准确率相当可观。
但是,这个预测并不能完全保证丢弃的 URL 都是与主题无关的,因此会有一些遗漏。同时,这种方法不能保证预测的页面都与主题相关,所以需要从预测的URL页面中提取页面内容主题,然后对比设置主题做出选择。
通过以上分析,得到了一个通用的解决方案。就是先通过URL解析,丢弃一些URL。下载页面后,提取页面内容的主题,并与预设的主题进行对比选择。最后进行数据清洗。
1.3 架构
深度聚焦爬虫的一般结构如下:
六大组件【控制中心】【下载模块】【提取模块】【清理模块】【复制模块】【资源模块】
控制模块:控制模块由程序进出、下载调度策略、提取调度策略、清理调度策略和URL重调度策略组成。
下载模块:根据控制中心发送的URL、IP、COOKIE等下载资源下载页面,并将下载结果返回给控制中心。
提取模块:接受控制中心下发的页面源代码和提取指标,根据提取指标提取源代码,并将提取结果返回给控制中心。
清洗模块分为文本清洗和URL清洗。文本清洗根据预设的主题和相应的主题相关性算法决定是丢弃文本还是将文本保存到库中。URL清洗就是根据URL分析结果来预测当前URL链接的页面是否与主题相关。如果相关,则将 URL 返回控制中心,否则丢弃 URL。
URL去重模块:针对部分主题突出的页面被多个页面链接,导致该页面大量重复下载,造成资源浪费和数据质量低下的情况,调用去重模块丢弃重复的 URL 并将非重复的 URL 返回到已下载资源模块的 URL 队列。
资源模块:保存下载所需的所有资源,包括代理IP、COOKIE、URL等信息。
2. 专注于爬虫的开发
大数据时代,对数据的多样性和针对性的要求越来越高。那么爬虫的架构更加灵活多变。比较常见的开源爬虫框架有Crawler4j、WebMagic、WebCollector、scrapy等。另一方面,对于爬虫的爬取,被爬取的网站也制定了相应的反爬措施。常见的反爬虫方法如下:
一、限制对经常访问 网站 的 IP 的访问。这是最常见的释放爬虫的方式。具体实施方式为,单位时间内对同一IP的请求次数达到网站设计的阈值,限制该IP访问。面对这种情况,可以制定合适的IP访问策略。
二、使用js和ajax技术的动态页面。此类网页的源代码中不收录所需的数据,并且该数据包存在于二次请求的返回文档中。对于这样的页面,可以分析请求过程,提取二次请求的URL,得到想要的数据。
三、其他情况:随着互联网的不断发展,各种反爬虫手段层出不穷。这就需要人们根据实际情况来解决问题。比如使用模拟浏览器(htmlunit、selenium)技术等等。
总之,没有不可变的互联网,也没有不可变的爬虫。只有拥抱变化,爬虫才能爬得更远。
3.爬虫在互联网金融领域的应用
聚焦爬虫作为数据的主要来源之一,说一下聚焦爬虫的应用场景,以我任职的普惠金融信息服务(上海)有限公司(以下简称普惠)为例例子。
3.1、网络借贷行业的数据驱动策略
数据驱动就是获取来贷款客户的指定数据,并根据这些数据和相应的一套算法策略为客户定义一个标签。贷款部门根据客户的标签决定是否向客户贷款以及贷款多少。这种定义标签的方式可以有效防止大部分欺诈性贷款的发生,从而规避风险。
那么,网贷平台如何利用大数据来判断客户的信用呢?大致可以分为两个方面:
1、查看此人的购物习惯、客户提供的计费信息等。此方法认为,如果一个人经常在网上购物,有详细的银行对账单,并且有正常的通话记录,那么这个人就是一个正常人,具有一定的财务能力。换句话说,这样的人能够偿还贷款。与发达国家完善的征信体系相比,这种评价方法在我国是可行的,并且在一定时期内是有效的。
2、另一方面,我们认为绝大多数骗子在完成贷款之前不会成为骗子。骗子在贷款之前都是骗子。那么在骗子的行骗生涯中,或多或少都会在网上留下痕迹。比如专门揭露骗子老赖的网站有很多,在一些社交网站上也有很多骗子被针对性曝光。对于这些暴露的数据,平台的大数据中心使用聚焦爬虫进行爬取,然后将爬取的数据保存到黑名单中。
从以上两点可以看出,无论是抓取交易票据等信息,还是抓取暴露的骗子等数据,都离不开聚焦爬虫的应用。
然而,随着互联网的不断发展变化,数据风控人员发现,通过传统方式控制风险越来越难。传统方法爬取的数据,基本上都是属于一个人的点数据,是片面的点数据。什么是点数据?如果把每个人都看成一个整体的数据,那么最形象的结构就是人脉数据网络。每个人都是网络中的一个节点,即每个人的数据都是点状数据。由于个人隐私的原因,我们不能也无法获取一个人的全方位数据,只能截取其中的一个或几个。
使用这些数据来判断一个人的信用等级有两个缺点。一是数据不完整会导致判断不准确。这个缺点是无法避免的。我们只能获取尽可能多的数据,制定更优化的算法模型;其次,随着互联网的发展,点状数据存在更多造假的可能性。例如,如果电子商务的交易记录被故意伪造,很容易产生一批完全符合高信用等级的交易记录。因此,点数据在未来风控体系中的占比会逐渐降低。
对应点数据的不足,爬虫社区有人提出了建立网络数据的可能性。其基本思路是以爬虫为重点,对各大社交网络网站进行爬取,基于这些数据建立人的关系网络,在关系网络的结构中,将补充各个维度的数据添加到每个人中。理想的数据集是每个来平台贷款的人都存在于平台大数据中心的人际关系网络中。我们知道与他们关系密切的人的标签(肖像)。
比如张三来贷款,大数据中心不仅需要知道张三的信用评价,还需要知道与张三关系密切的几个人的信用评价。这有什么用?假设张三的贷款场景如下:张三通过大数据中心的传统信用评价方式获得了良好的信用评价。但我们通过关系网发现,与张三关系密切的人中有不少在信用评价中被评为低信用,甚至被列入黑名单。这时候,我们不得不怀疑张三的数据是否是精心编造的。根据事物就像群体,人是组合在一起的道理,我们认为这种怀疑是必要的。
张三人物关系网络图:
从上图可以看出,张三良好的信用评价并不可靠,贷款会给张三带来很大的风险。显然,传统的风控手段无法避免这种风险,而且这种风险会随着欺诈者对贷款公司信用评估方式的越来越了解而增加。试想,在未来,由于欺诈贷方对公司的风险控制有一个大致的了解,他们在某一方面已经形成了良好的记录。如果大数据中心爬取了这些数据,误判了信用评级,贷款公司所承担的风险将急剧扩大。
鉴于未来这种风险,人脉数据网络提供了解决的可能。如果没有完善可靠的官方征信系统,个人关系数据网络将是未来无抵押贷款公司风控的主流方式。然而,构建人物关系数据网络并不是一朝一夕的事情。
4.结束语
每一个社交网站都有海量数据,与海量数据成正比的是社交网站的反爬虫策略。这对爬虫提出了更高更严格的要求,也细化了不同爬虫之间的差异。然而,不变性并不是互联网的主题。依靠互联网生存的企业必须学会拥抱变化,甚至预测变化,这样才能在未来乘风破浪,越走越远。 查看全部
htmlunit抓取动态网页(目录1.聚焦爬虫的发展在互联网金融领域应用)
导读
马云说,大数据时代已经到来。现在有太多的互联网公司在做大数据,每个公司都有不止一个数据源。占很大比例的数据源之一是网络爬虫。但是,不同的公司有不同的业务背景,需要不同类型的数据。与用于搜索网站的通用爬虫不同,专注爬虫开始被越来越多的提及。
内容
1. 关注爬虫原理
2. 专注于爬虫的开发
3. 爬虫在互联网金融领域的应用
4. 结论
1.专注于爬虫的原理
1.1概念
聚焦爬虫,又称主题爬虫(或专业爬虫),是一种“针对特定主题”的网络爬虫。它与我们通常所说的爬虫(万能爬虫)的区别在于,聚焦爬虫在实现网络爬虫时需要进行主题筛选。它试图确保只抓取与主题相关的网页。
1.2 关注爬虫的分类
焦点爬虫主要分为两类。一种是浅焦点爬虫。所谓浅焦点爬虫,就是爬虫程序抓取特定网站的所有信息。它的工作方式和一般的爬虫几乎一样,唯一不同的是种子URL的选择决定了爬取内容的一致性,核心是种子URL的选择。另一种是深度聚焦爬虫。深度聚焦爬虫是指在大量不同内容的网页中,通过主题相关性算法,选择具有相似主题的URL和内容进行爬取。它的核心是如何判断抓取到的 URL 和页面内容是否与主题相关。
关系如下:
从图中可以看出,浅焦点爬虫可以看成是一种仅限于单一主题网站的通用爬虫,所以我们通常所说的焦点爬虫大多是指深度焦点爬虫。
1.2.1 浅焦点爬虫
浅焦点爬虫从一个或几个初始网页的URL开始,(例如分类信息网)获取初始网页上的URL,在抓取网页的过程中,不断地从原创网页中提取新的URL当前页面并将它们放入队列中,直到系统满意为止。某些停止条件。
其工作流程如下:
可以看出,浅焦点爬虫的基本原理和一般爬虫是一样的。使用主题网站可以保证爬取内容的主题一致。
1.2.2 深度关注爬行动物
Deep Focus Crawler 的主要特点是主题一致性。然而,在浩瀚的互联网大数据海洋中,要保证抓取到的数据的一致性并不是一件简单的事情。对于不同的数据需求,所需的策略和方法没有统一的答案。这里不谈具体的解决方案,只讨论常见的解决方案。
一、对于页面内容
这个解决方案是先爬取页面,不考虑页面的主题。对页面进行简单去噪后,使用主题提取策略提取处理后的页面内容的主题,最后对比设置的主题,如果主题一致,或者在一定的阈值内,则保存页面进行进一步的数据清洗。如果主题偏差超过阈值,则页面被简单地丢弃。
这种方法的优点是链接页面被完全覆盖,不会有数据遗漏。但缺点也很致命,那就是全覆盖页面,其中很大一部分是与主题无关的废弃页面,大大减慢了爬虫爬取数据的速度。到了后期,爬取数据的速度将是无法接受的。
二、对于 URL
上面介绍的浅焦点爬虫的核心是选择合适的种子URL。这些种子 URL 主要是主题 网站 的入口 URL。
网上的网站一般都有固定的主题,同一个网站中相同主题的页面的URL有一定的规律可循。由此,自然而然地产生了通过URL来预测页面主题的想法。另外,页面中的大部分超链接都有锚文本,锚文本基本上可以看作是对目标页面的概括描述。结合对URL的分析和对锚文本的分析,目标页面的话题预测准确率相当可观。
但是,这个预测并不能完全保证丢弃的 URL 都是与主题无关的,因此会有一些遗漏。同时,这种方法不能保证预测的页面都与主题相关,所以需要从预测的URL页面中提取页面内容主题,然后对比设置主题做出选择。
通过以上分析,得到了一个通用的解决方案。就是先通过URL解析,丢弃一些URL。下载页面后,提取页面内容的主题,并与预设的主题进行对比选择。最后进行数据清洗。
1.3 架构
深度聚焦爬虫的一般结构如下:
六大组件【控制中心】【下载模块】【提取模块】【清理模块】【复制模块】【资源模块】
控制模块:控制模块由程序进出、下载调度策略、提取调度策略、清理调度策略和URL重调度策略组成。
下载模块:根据控制中心发送的URL、IP、COOKIE等下载资源下载页面,并将下载结果返回给控制中心。
提取模块:接受控制中心下发的页面源代码和提取指标,根据提取指标提取源代码,并将提取结果返回给控制中心。
清洗模块分为文本清洗和URL清洗。文本清洗根据预设的主题和相应的主题相关性算法决定是丢弃文本还是将文本保存到库中。URL清洗就是根据URL分析结果来预测当前URL链接的页面是否与主题相关。如果相关,则将 URL 返回控制中心,否则丢弃 URL。
URL去重模块:针对部分主题突出的页面被多个页面链接,导致该页面大量重复下载,造成资源浪费和数据质量低下的情况,调用去重模块丢弃重复的 URL 并将非重复的 URL 返回到已下载资源模块的 URL 队列。
资源模块:保存下载所需的所有资源,包括代理IP、COOKIE、URL等信息。
2. 专注于爬虫的开发
大数据时代,对数据的多样性和针对性的要求越来越高。那么爬虫的架构更加灵活多变。比较常见的开源爬虫框架有Crawler4j、WebMagic、WebCollector、scrapy等。另一方面,对于爬虫的爬取,被爬取的网站也制定了相应的反爬措施。常见的反爬虫方法如下:
一、限制对经常访问 网站 的 IP 的访问。这是最常见的释放爬虫的方式。具体实施方式为,单位时间内对同一IP的请求次数达到网站设计的阈值,限制该IP访问。面对这种情况,可以制定合适的IP访问策略。
二、使用js和ajax技术的动态页面。此类网页的源代码中不收录所需的数据,并且该数据包存在于二次请求的返回文档中。对于这样的页面,可以分析请求过程,提取二次请求的URL,得到想要的数据。
三、其他情况:随着互联网的不断发展,各种反爬虫手段层出不穷。这就需要人们根据实际情况来解决问题。比如使用模拟浏览器(htmlunit、selenium)技术等等。
总之,没有不可变的互联网,也没有不可变的爬虫。只有拥抱变化,爬虫才能爬得更远。
3.爬虫在互联网金融领域的应用
聚焦爬虫作为数据的主要来源之一,说一下聚焦爬虫的应用场景,以我任职的普惠金融信息服务(上海)有限公司(以下简称普惠)为例例子。
3.1、网络借贷行业的数据驱动策略
数据驱动就是获取来贷款客户的指定数据,并根据这些数据和相应的一套算法策略为客户定义一个标签。贷款部门根据客户的标签决定是否向客户贷款以及贷款多少。这种定义标签的方式可以有效防止大部分欺诈性贷款的发生,从而规避风险。
那么,网贷平台如何利用大数据来判断客户的信用呢?大致可以分为两个方面:
1、查看此人的购物习惯、客户提供的计费信息等。此方法认为,如果一个人经常在网上购物,有详细的银行对账单,并且有正常的通话记录,那么这个人就是一个正常人,具有一定的财务能力。换句话说,这样的人能够偿还贷款。与发达国家完善的征信体系相比,这种评价方法在我国是可行的,并且在一定时期内是有效的。
2、另一方面,我们认为绝大多数骗子在完成贷款之前不会成为骗子。骗子在贷款之前都是骗子。那么在骗子的行骗生涯中,或多或少都会在网上留下痕迹。比如专门揭露骗子老赖的网站有很多,在一些社交网站上也有很多骗子被针对性曝光。对于这些暴露的数据,平台的大数据中心使用聚焦爬虫进行爬取,然后将爬取的数据保存到黑名单中。
从以上两点可以看出,无论是抓取交易票据等信息,还是抓取暴露的骗子等数据,都离不开聚焦爬虫的应用。
然而,随着互联网的不断发展变化,数据风控人员发现,通过传统方式控制风险越来越难。传统方法爬取的数据,基本上都是属于一个人的点数据,是片面的点数据。什么是点数据?如果把每个人都看成一个整体的数据,那么最形象的结构就是人脉数据网络。每个人都是网络中的一个节点,即每个人的数据都是点状数据。由于个人隐私的原因,我们不能也无法获取一个人的全方位数据,只能截取其中的一个或几个。
使用这些数据来判断一个人的信用等级有两个缺点。一是数据不完整会导致判断不准确。这个缺点是无法避免的。我们只能获取尽可能多的数据,制定更优化的算法模型;其次,随着互联网的发展,点状数据存在更多造假的可能性。例如,如果电子商务的交易记录被故意伪造,很容易产生一批完全符合高信用等级的交易记录。因此,点数据在未来风控体系中的占比会逐渐降低。
对应点数据的不足,爬虫社区有人提出了建立网络数据的可能性。其基本思路是以爬虫为重点,对各大社交网络网站进行爬取,基于这些数据建立人的关系网络,在关系网络的结构中,将补充各个维度的数据添加到每个人中。理想的数据集是每个来平台贷款的人都存在于平台大数据中心的人际关系网络中。我们知道与他们关系密切的人的标签(肖像)。
比如张三来贷款,大数据中心不仅需要知道张三的信用评价,还需要知道与张三关系密切的几个人的信用评价。这有什么用?假设张三的贷款场景如下:张三通过大数据中心的传统信用评价方式获得了良好的信用评价。但我们通过关系网发现,与张三关系密切的人中有不少在信用评价中被评为低信用,甚至被列入黑名单。这时候,我们不得不怀疑张三的数据是否是精心编造的。根据事物就像群体,人是组合在一起的道理,我们认为这种怀疑是必要的。
张三人物关系网络图:
从上图可以看出,张三良好的信用评价并不可靠,贷款会给张三带来很大的风险。显然,传统的风控手段无法避免这种风险,而且这种风险会随着欺诈者对贷款公司信用评估方式的越来越了解而增加。试想,在未来,由于欺诈贷方对公司的风险控制有一个大致的了解,他们在某一方面已经形成了良好的记录。如果大数据中心爬取了这些数据,误判了信用评级,贷款公司所承担的风险将急剧扩大。
鉴于未来这种风险,人脉数据网络提供了解决的可能。如果没有完善可靠的官方征信系统,个人关系数据网络将是未来无抵押贷款公司风控的主流方式。然而,构建人物关系数据网络并不是一朝一夕的事情。
4.结束语
每一个社交网站都有海量数据,与海量数据成正比的是社交网站的反爬虫策略。这对爬虫提出了更高更严格的要求,也细化了不同爬虫之间的差异。然而,不变性并不是互联网的主题。依靠互联网生存的企业必须学会拥抱变化,甚至预测变化,这样才能在未来乘风破浪,越走越远。
htmlunit抓取动态网页(HtmlUnit在多线程环境下怎么使用才能避免网页抓取失败的问题)
网站优化 • 优采云 发表了文章 • 0 个评论 • 65 次浏览 • 2022-01-11 18:06
今天在网上看到一个问题,问如何在多线程环境下使用HtmlUnit,避免网页爬取失败。下面,根据我自己的经验,我将讨论解决这个问题的方法。
这个问题的原因其实很简单。例如,线程 A 正在使用 WebClient 对象来爬取网页。在整个爬取过程结束之前,当前线程被CPU挂起,所以线程B被激活,然后B使用A正在使用的WebClient对象去抓取其他网页,那么这个时候,WebCLient对象就会清除刚刚完成的工作留下的数据,以此类推。共享 WebClient 的线程越多,问题发生的频率就越高。页面丢失的概率也更高。但其实这个问题并不难解决,它的解决方案也有广泛的适用性:无论是任何对象,在多线程环境下遇到资源共享问题时,通常有两种解决方案,
早在JDK1.2版本就提供的java.lang.ThreadLocal和ThreadLocal,为解决多线程程序的并发问题提供了新思路。使用这个工具类,你可以编写精美的多线程程序。这个想法是为每个线程保留变量的本地副本,以确保变量不与其他线程共享 - 一种保守但有效的方法。本文的目的不是介绍ThreadLocal的用法(具体用法请参考百度百科),而是想用ThreadLocal解决多线程环境下HtmlUnit的WebClient对象的共享问题。
请看如何使用 ThreadLocal 对象来解决上述问题:
package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.BrowserVersion;import com.gargoylesoftware.htmlunit.WebClient;/** * * @author Shenghany * @date 2013-5-27 */publicclassThreadLocalClientFactory{//单例工厂模式privatefinalstaticThreadLocalClientFactory instance =newThreadLocalClientFactory();//线程的本地实例存储器,用于存储WebClient实例privateThreadLocal clientThreadLocal;/** * 构造方法,初始时线程的本地变量存储器 */publicThreadLocalClientFactory(){clientThreadLocal =newThreadLocal();}/** * 获取工厂实例 * @return 工厂实例 */publicstaticThreadLocalClientFactory getInstance(){return instance;}/** * 获取一个模拟FireFox3.6版本的WebClient实例 * @return 模拟FireFox3.6版本的WebClient实例 */publicWebClient getClient(){WebClient client =null;/** * 如果当前线程已有WebClient实例,则直接返回该实例 * 否则重新创建一个WebClient实例并存储于当前线程的本地变量存储器 */if((client = clientThreadLocal.get())==null){client =newWebClient(BrowserVersion.FIREFOX_3_6);client.setCssEnabled(false);client.setJavaScriptEnabled(false);clientThreadLocal.set(client);System.out.println("为线程 [ "+Thread.currentThread().getName()+" ] 创建新的WebClient实例!");}else{System.out.println("线程 [ "+Thread.currentThread().getName()+" ] 已有WebClient实例,直接使用. . .");}return client;}}
测试代码:
<p>package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.WebClient;import com.gargoylesoftware.htmlunit.html.HtmlPage;/** * * @author Shenghany * @date 2013-5-27 */publicclassThreadLocalHtmlUnitTester{/** * 获取目标页面,并打印网页标题 * @param url 目标页面地址 */publicstaticvoid getPage(String url){//从工厂中获取一个WebClient实例WebClient client =ThreadLocalClientFactory.getInstance().getClient();try{//抓取网页HtmlPage page =(HtmlPage)client.getPage(url);//打印当前线程名称及网页标题System.out.println(Thread.currentThread().getName()+" [ "+ url +" ] : "+ page.getTitleText());}catch(Exception e){e.printStackTrace();}}/** * 测试程序执行入口 * @param s */publicstaticvoid main(String[] s){//文章编号int postId =50;//目标网页的部分内容String http ="http://www.yshjava.cn/post/4";/** * 共16篇文章,每个线程抓取两篇,共计将产生8个线程 */for(int i = postId; i 查看全部
htmlunit抓取动态网页(HtmlUnit在多线程环境下怎么使用才能避免网页抓取失败的问题)
今天在网上看到一个问题,问如何在多线程环境下使用HtmlUnit,避免网页爬取失败。下面,根据我自己的经验,我将讨论解决这个问题的方法。
这个问题的原因其实很简单。例如,线程 A 正在使用 WebClient 对象来爬取网页。在整个爬取过程结束之前,当前线程被CPU挂起,所以线程B被激活,然后B使用A正在使用的WebClient对象去抓取其他网页,那么这个时候,WebCLient对象就会清除刚刚完成的工作留下的数据,以此类推。共享 WebClient 的线程越多,问题发生的频率就越高。页面丢失的概率也更高。但其实这个问题并不难解决,它的解决方案也有广泛的适用性:无论是任何对象,在多线程环境下遇到资源共享问题时,通常有两种解决方案,
早在JDK1.2版本就提供的java.lang.ThreadLocal和ThreadLocal,为解决多线程程序的并发问题提供了新思路。使用这个工具类,你可以编写精美的多线程程序。这个想法是为每个线程保留变量的本地副本,以确保变量不与其他线程共享 - 一种保守但有效的方法。本文的目的不是介绍ThreadLocal的用法(具体用法请参考百度百科),而是想用ThreadLocal解决多线程环境下HtmlUnit的WebClient对象的共享问题。
请看如何使用 ThreadLocal 对象来解决上述问题:
package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.BrowserVersion;import com.gargoylesoftware.htmlunit.WebClient;/** * * @author Shenghany * @date 2013-5-27 */publicclassThreadLocalClientFactory{//单例工厂模式privatefinalstaticThreadLocalClientFactory instance =newThreadLocalClientFactory();//线程的本地实例存储器,用于存储WebClient实例privateThreadLocal clientThreadLocal;/** * 构造方法,初始时线程的本地变量存储器 */publicThreadLocalClientFactory(){clientThreadLocal =newThreadLocal();}/** * 获取工厂实例 * @return 工厂实例 */publicstaticThreadLocalClientFactory getInstance(){return instance;}/** * 获取一个模拟FireFox3.6版本的WebClient实例 * @return 模拟FireFox3.6版本的WebClient实例 */publicWebClient getClient(){WebClient client =null;/** * 如果当前线程已有WebClient实例,则直接返回该实例 * 否则重新创建一个WebClient实例并存储于当前线程的本地变量存储器 */if((client = clientThreadLocal.get())==null){client =newWebClient(BrowserVersion.FIREFOX_3_6);client.setCssEnabled(false);client.setJavaScriptEnabled(false);clientThreadLocal.set(client);System.out.println("为线程 [ "+Thread.currentThread().getName()+" ] 创建新的WebClient实例!");}else{System.out.println("线程 [ "+Thread.currentThread().getName()+" ] 已有WebClient实例,直接使用. . .");}return client;}}
测试代码:
<p>package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.WebClient;import com.gargoylesoftware.htmlunit.html.HtmlPage;/** * * @author Shenghany * @date 2013-5-27 */publicclassThreadLocalHtmlUnitTester{/** * 获取目标页面,并打印网页标题 * @param url 目标页面地址 */publicstaticvoid getPage(String url){//从工厂中获取一个WebClient实例WebClient client =ThreadLocalClientFactory.getInstance().getClient();try{//抓取网页HtmlPage page =(HtmlPage)client.getPage(url);//打印当前线程名称及网页标题System.out.println(Thread.currentThread().getName()+" [ "+ url +" ] : "+ page.getTitleText());}catch(Exception e){e.printStackTrace();}}/** * 测试程序执行入口 * @param s */publicstaticvoid main(String[] s){//文章编号int postId =50;//目标网页的部分内容String http ="http://www.yshjava.cn/post/4";/** * 共16篇文章,每个线程抓取两篇,共计将产生8个线程 */for(int i = postId; i
htmlunit抓取动态网页(Java环境下的一下配置实现思路介绍-苏州安嘉 )
网站优化 • 优采云 发表了文章 • 0 个评论 • 58 次浏览 • 2022-01-11 17:17
)
爬取网页数据时,传统的jsoup方案只能对静态页面有效,而一些网页数据往往是由js生成的,此时就需要其他的方案了。
第一个思路是分析js程序,再次爬取js请求,适合爬取特定页面,但要实现不同目标url的通用性比较麻烦。
第二种思路,也比较成熟,就是使用第三方驱动渲染页面,然后下载。这是第二个实现思路。
Selenium 是一个模拟浏览器的自动化测试工具。它提供了一组 API 来与真正的浏览器内核交互。
Java环境下的maven配置如下:
org.seleniumhq.selenium
selenium-java
2.46.0
第三方驱动主要有IEDriver、FirefoxDriver、ChromeDriver、HtmlUnitDriver。
htmlUnit 也是一个自动化测试的工具。您可以使用 HtmlUnit 来模拟浏览器运行并获取执行的 html 页面。其中,HtmlUnitDriver是对htmlUnit的封装。
由于htmlunit对js解析的支持有限,在实际项目中并不常用。
以chrome为例,下载对应的驱动:.
下载驱动时,需要注意与selenium版本的兼容性。可能有例外。一般来说,最好下载最新版本。
在运行程序之前,一定要指定驱动位置,比如在Windows下
System.getProperties().setProperty("webdriver.chrome.driver",
"D:\\chromedriver\\chromedriver.exe");
获取整个页面
public static void testChromeDriver() {
System.getProperties().setProperty("webdriver.chrome.driver",
"D:\\chromedriver\\chromedriver.exe");
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://picture.youth.cn/qtdb/2 ... 6quot;);
String responseBody = webDriver.getPageSource();
System.out.println(responseBody);
webDriver.close();
} 查看全部
htmlunit抓取动态网页(Java环境下的一下配置实现思路介绍-苏州安嘉
)
爬取网页数据时,传统的jsoup方案只能对静态页面有效,而一些网页数据往往是由js生成的,此时就需要其他的方案了。
第一个思路是分析js程序,再次爬取js请求,适合爬取特定页面,但要实现不同目标url的通用性比较麻烦。
第二种思路,也比较成熟,就是使用第三方驱动渲染页面,然后下载。这是第二个实现思路。
Selenium 是一个模拟浏览器的自动化测试工具。它提供了一组 API 来与真正的浏览器内核交互。
Java环境下的maven配置如下:
org.seleniumhq.selenium
selenium-java
2.46.0
第三方驱动主要有IEDriver、FirefoxDriver、ChromeDriver、HtmlUnitDriver。
htmlUnit 也是一个自动化测试的工具。您可以使用 HtmlUnit 来模拟浏览器运行并获取执行的 html 页面。其中,HtmlUnitDriver是对htmlUnit的封装。
由于htmlunit对js解析的支持有限,在实际项目中并不常用。
以chrome为例,下载对应的驱动:.
下载驱动时,需要注意与selenium版本的兼容性。可能有例外。一般来说,最好下载最新版本。
在运行程序之前,一定要指定驱动位置,比如在Windows下
System.getProperties().setProperty("webdriver.chrome.driver",
"D:\\chromedriver\\chromedriver.exe");
获取整个页面
public static void testChromeDriver() {
System.getProperties().setProperty("webdriver.chrome.driver",
"D:\\chromedriver\\chromedriver.exe");
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://picture.youth.cn/qtdb/2 ... 6quot;);
String responseBody = webDriver.getPageSource();
System.out.println(responseBody);
webDriver.close();
}
htmlunit抓取动态网页(1.HtmlUnit的学习方法是什么?怎么样?HtmlUnit)
网站优化 • 优采云 发表了文章 • 0 个评论 • 59 次浏览 • 2022-01-10 20:07
1.HtmlUnit 是一个用java 编写的无界面浏览器,它可以模拟html 文档、通过API 调用页面、填写表单、点击链接等等。像普通浏览器一样运行。通常用于测试和从网页中抓取信息。而HtmlUnit有HttpClient和soup的功能,但是速度比较慢,但是如果取消它解析css和js的功能,速度也会有所提升,默认开启。
2.这里,HtmlUnit是用来爬取数据的,主要是为了获取他的js和css。
3.主要代码如下
package com.los;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.los.util.DownlandPic;
import java.io.IOException;
import java.util.regex.Pattern;
public class HtmlUnitTest {
public static void main(String[] args) throws IOException {
DownlandPic dd = new DownlandPic();
WebClient webClient = new WebClient();//实例化web客户端
//http://www.bdqn.cn/ https://www.baidu.com/?tn=78000241_22_hao_pg
String url = "http://www.bdqn.cn/";
HtmlPage page = webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000); //等侍js脚本执行完成
System.out.println(page.asXml());
DomNodeList img = page.getElementsByTagName("script");
for (int i=0;i 0) {
output.write(buffer, 0, length);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static int getCharacterPosition3(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 2){
break;
}
}
return slashMatcher.start();
}
public static int getCharacterPosition4(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 3){
break;
}
}
return slashMatcher.start();
}
public static void main(String[] args) {
String content = "<img class=\"lazy\" data-original=\"/img/newImg/news_img2.jpg\" src=\"/img/newImg/news2.jpg\" style=\"display: block;\"/>";
System.out.println(getCharacterPosition3(content));
System.out.println(getCharacterPosition4(content));
String substring = content.substring(getCharacterPosition3(content), getCharacterPosition4(content));
System.out.println(substring);
}
}
3.因为这里网页中的图片地址是相对路径,所以下载的时候到页面中找到它的绝对路径,拼接在下载地址中。下载的路径必须与图片标签中的地址对应爬取后存储在本地页面,否则无法找到。
3.之所以在匹配“时写2和3是根据这里爬取的数据。
4.相对于其他爬取网页的写法,这个可能更简单,但是更能体现效果。如有错误,请多多指教。至于页面不会显示,涉及隐私。
5.了解HtmlUnit请参考:地址 查看全部
htmlunit抓取动态网页(1.HtmlUnit的学习方法是什么?怎么样?HtmlUnit)
1.HtmlUnit 是一个用java 编写的无界面浏览器,它可以模拟html 文档、通过API 调用页面、填写表单、点击链接等等。像普通浏览器一样运行。通常用于测试和从网页中抓取信息。而HtmlUnit有HttpClient和soup的功能,但是速度比较慢,但是如果取消它解析css和js的功能,速度也会有所提升,默认开启。
2.这里,HtmlUnit是用来爬取数据的,主要是为了获取他的js和css。
3.主要代码如下
package com.los;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.los.util.DownlandPic;
import java.io.IOException;
import java.util.regex.Pattern;
public class HtmlUnitTest {
public static void main(String[] args) throws IOException {
DownlandPic dd = new DownlandPic();
WebClient webClient = new WebClient();//实例化web客户端
//http://www.bdqn.cn/ https://www.baidu.com/?tn=78000241_22_hao_pg
String url = "http://www.bdqn.cn/";
HtmlPage page = webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000); //等侍js脚本执行完成
System.out.println(page.asXml());
DomNodeList img = page.getElementsByTagName("script");
for (int i=0;i 0) {
output.write(buffer, 0, length);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static int getCharacterPosition3(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 2){
break;
}
}
return slashMatcher.start();
}
public static int getCharacterPosition4(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 3){
break;
}
}
return slashMatcher.start();
}
public static void main(String[] args) {
String content = "<img class=\"lazy\" data-original=\"/img/newImg/news_img2.jpg\" src=\"/img/newImg/news2.jpg\" style=\"display: block;\"/>";
System.out.println(getCharacterPosition3(content));
System.out.println(getCharacterPosition4(content));
String substring = content.substring(getCharacterPosition3(content), getCharacterPosition4(content));
System.out.println(substring);
}
}
3.因为这里网页中的图片地址是相对路径,所以下载的时候到页面中找到它的绝对路径,拼接在下载地址中。下载的路径必须与图片标签中的地址对应爬取后存储在本地页面,否则无法找到。
3.之所以在匹配“时写2和3是根据这里爬取的数据。

4.相对于其他爬取网页的写法,这个可能更简单,但是更能体现效果。如有错误,请多多指教。至于页面不会显示,涉及隐私。
5.了解HtmlUnit请参考:地址
htmlunit抓取动态网页(搜索引擎更喜欢静态页面还是动态页面之前?(图))
网站优化 • 优采云 发表了文章 • 0 个评论 • 57 次浏览 • 2022-01-10 10:07
项目投资找A5快速获取精准代理商名单
做网站优化,到底是静态页面好还是动态页面好,一直是众多优化者争论不休的问题。有的站长说搜索引擎喜欢抓取一些静态页面,就像野兽在打猎的时候,总是喜欢先抓到不动的难缠的物体,而这些站长认为静态页面在搜索引擎的猛兽眼中. 所以。
在知道搜索引擎更喜欢静态页面还是动态页面之前,有必要普及一下网站的基础知识:什么是静态页面?简单来说就是页面的URL不收录一些动态元素,比如“?,%,&”,那么只要页面URL地址中收录这些元素,就称为动态页面。
从上面的意思我们知道,静态页面和动态页面最大的区别在于是否收录一些动态元素,而这些动态元素会导致搜索引擎蜘蛛无法理解早期的搜索引擎。以为是多个不同的URL,就会不断爬取这个动态的URL地址,造成“搜索引擎蜘蛛黑洞”。
所以早期的搜索引擎真的不喜欢动态页面,更喜欢抓取静态页面。但随着搜索引擎技术的不断发展,历届各大搜索引擎公司都宣称可以爬取和爬取动态页面,对动态页面和静态页面一视同仁,包括谷歌、百度、搜搜。
说一下我个人的看法,由于搜索引擎的进步,动态页面也可以被爬取,爬得很好。因此,当 URL 中的动态元素尽可能少时,可以使用动态页面。这里给你举个例子,.***.net/wp-login.php?redirect_to=http%3A%2F%2F###.net%2Fwp-admin%2F&reauth=1,很明显是一个URL URL动态网页,但收录的动态元素太多,对搜索引擎不友好,不可用。
。***。网/?p=167,这种网址也是动态的,如果只收录一个“?”,很多搜索引擎都可以抓取到。我自己也用这种动态网址做了几个网站,一段时间后,几个网站的收录和排名都很好。所以到底搜索引擎更喜欢静态页面还是动态页面,我觉得应该差不多吧。 查看全部
htmlunit抓取动态网页(搜索引擎更喜欢静态页面还是动态页面之前?(图))
项目投资找A5快速获取精准代理商名单
做网站优化,到底是静态页面好还是动态页面好,一直是众多优化者争论不休的问题。有的站长说搜索引擎喜欢抓取一些静态页面,就像野兽在打猎的时候,总是喜欢先抓到不动的难缠的物体,而这些站长认为静态页面在搜索引擎的猛兽眼中. 所以。
在知道搜索引擎更喜欢静态页面还是动态页面之前,有必要普及一下网站的基础知识:什么是静态页面?简单来说就是页面的URL不收录一些动态元素,比如“?,%,&”,那么只要页面URL地址中收录这些元素,就称为动态页面。
从上面的意思我们知道,静态页面和动态页面最大的区别在于是否收录一些动态元素,而这些动态元素会导致搜索引擎蜘蛛无法理解早期的搜索引擎。以为是多个不同的URL,就会不断爬取这个动态的URL地址,造成“搜索引擎蜘蛛黑洞”。
所以早期的搜索引擎真的不喜欢动态页面,更喜欢抓取静态页面。但随着搜索引擎技术的不断发展,历届各大搜索引擎公司都宣称可以爬取和爬取动态页面,对动态页面和静态页面一视同仁,包括谷歌、百度、搜搜。
说一下我个人的看法,由于搜索引擎的进步,动态页面也可以被爬取,爬得很好。因此,当 URL 中的动态元素尽可能少时,可以使用动态页面。这里给你举个例子,.***.net/wp-login.php?redirect_to=http%3A%2F%2F###.net%2Fwp-admin%2F&reauth=1,很明显是一个URL URL动态网页,但收录的动态元素太多,对搜索引擎不友好,不可用。
。***。网/?p=167,这种网址也是动态的,如果只收录一个“?”,很多搜索引擎都可以抓取到。我自己也用这种动态网址做了几个网站,一段时间后,几个网站的收录和排名都很好。所以到底搜索引擎更喜欢静态页面还是动态页面,我觉得应该差不多吧。
htmlunit抓取动态网页(抓一个今日头条的首页内容解决方案-苏州安嘉)
网站优化 • 优采云 发表了文章 • 0 个评论 • 82 次浏览 • 2022-01-08 13:06
不知道大家在使用jsoup的过程中是否遇到过爬取内容,发现有些网页中的内容是通过javascript异步加载的,导致我们的爬虫空手返回(只抓一个网页的外框) .
当我第一次遇到这个问题时,我想到了两个解决方案:
在等待网页异步加载后,使用类似于 Python 中延迟加载的方法对异步加载的网页进行爬取。使用一种特殊的方法来模拟被爬取的网页框架内的 JavaScript 代码的执行,最终到达完整的网页。
在搜索引擎的帮助下,决定使用方案二来解决这个问题。解决方案1中没有搜索到更好的第三方库。在java中使用解决方案1解决此问题的朋友希望与下一个讨论,非常感谢。
案例很简单,抓取一条今日头条的首页内容。你可以看一下今日头条的首页,里面的内容是异步加载的。
添加jsoup和htmlunit依赖
org.jsoup
jsoup
1.10.2
net.sourceforge.htmlunit
htmlunit
2.25
12345678910
首先,我们单独使用jsoup来解析今日头条的首页
String url = "https://www.toutiao.com/";
Connection connect = Jsoup.connect(url);
Document document = connect.get();
System.out.println(document);
1234
↑ 这里只能获取网页的框架内容,不能获取首页的新闻内容
接下来,我们使用htmlunit来尝试
//构造一个webClient 模拟Chrome 浏览器
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//屏蔽日志信息
LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log",
"org.apache.commons.logging.impl.NoOpLog");
java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
//支持JavaScript
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setActiveXNative(false);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setTimeout(5000);
HtmlPage rootPage = webClient.getPage(url);
//设置一个运行JavaScript的时间
webClient.waitForBackgroundJavaScript(5000);
String html = rootPage.asXml();
Document document = Jsoup.parse(html);
12345678910111213141516171819
<a target="_blank" style="box-sizing: border-box; color: rgb(12, 137, 207);"></a>
这为我们提供了一个运行 JavaScript 的完整源页面 查看全部
htmlunit抓取动态网页(抓一个今日头条的首页内容解决方案-苏州安嘉)
不知道大家在使用jsoup的过程中是否遇到过爬取内容,发现有些网页中的内容是通过javascript异步加载的,导致我们的爬虫空手返回(只抓一个网页的外框) .
当我第一次遇到这个问题时,我想到了两个解决方案:
在等待网页异步加载后,使用类似于 Python 中延迟加载的方法对异步加载的网页进行爬取。使用一种特殊的方法来模拟被爬取的网页框架内的 JavaScript 代码的执行,最终到达完整的网页。
在搜索引擎的帮助下,决定使用方案二来解决这个问题。解决方案1中没有搜索到更好的第三方库。在java中使用解决方案1解决此问题的朋友希望与下一个讨论,非常感谢。
案例很简单,抓取一条今日头条的首页内容。你可以看一下今日头条的首页,里面的内容是异步加载的。
添加jsoup和htmlunit依赖
org.jsoup
jsoup
1.10.2
net.sourceforge.htmlunit
htmlunit
2.25
12345678910
首先,我们单独使用jsoup来解析今日头条的首页
String url = "https://www.toutiao.com/";
Connection connect = Jsoup.connect(url);
Document document = connect.get();
System.out.println(document);
1234
↑ 这里只能获取网页的框架内容,不能获取首页的新闻内容
接下来,我们使用htmlunit来尝试
//构造一个webClient 模拟Chrome 浏览器
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//屏蔽日志信息
LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log",
"org.apache.commons.logging.impl.NoOpLog");
java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
//支持JavaScript
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setActiveXNative(false);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setTimeout(5000);
HtmlPage rootPage = webClient.getPage(url);
//设置一个运行JavaScript的时间
webClient.waitForBackgroundJavaScript(5000);
String html = rootPage.asXml();
Document document = Jsoup.parse(html);
12345678910111213141516171819
<a target="_blank" style="box-sizing: border-box; color: rgb(12, 137, 207);">

这为我们提供了一个运行 JavaScript 的完整源页面
htmlunit抓取动态网页(中小微公司网络爬虫技术总结及解决办法(一))
网站优化 • 优采云 发表了文章 • 0 个评论 • 85 次浏览 • 2022-02-01 04:27
网络爬虫技术总结
对于大数据行业来说,数据的价值不言而喻。在这个信息爆炸的时代,互联网上的信息数据太多了。对于中小微企业来说,合理使用爬虫爬取有价值的数据,是为了弥补自身先天的数据短缺。板子的最佳选择,本文主要从爬虫原理、架构、分类和反爬虫技术方面总结了爬虫技术。
1、爬虫技术概述
网络爬虫是一种程序或脚本,它根据一定的规则自动爬取万维网上的信息。它们广泛应用于互联网搜索引擎或其他类似的网站,并且可以自动采集所有它可以访问的页面的内容来获取或更新这些网站的内容和检索方式. 从功能上来说,爬虫一般分为数据采集、处理、存储三部分。
传统爬虫从一个或多个初始网页的URL开始,获取初始网页上的URL。在对网页进行爬取的过程中,不断地从当前页面中提取新的 URL 并放入队列中,直到满足系统的某些停止条件。焦点爬虫的工作流程比较复杂。它需要按照一定的网页分析算法过滤掉与主题无关的链接,保留有用的链接,并放入等待抓取的URL队列中。然后,它会根据一定的搜索策略从队列中选择下一个要爬取的网页URL,并重复上述过程,直到达到系统的一定条件并停止。另外,爬虫爬取的所有网页都会被系统存储,进行一定的分析、过滤和索引,以供后续查询和检索;对于重点爬虫来说,这个过程中得到的分析结果也可能对后续的爬取过程给出反馈和指导。
与通用网络爬虫相比,聚焦爬虫还需要解决三个主要问题:
(1)爬取目标的描述或定义;
(2)网页或数据的分析和过滤;
(3)URL 的搜索策略。
2、爬虫原理
2.1网络爬虫原理
网络爬虫系统的功能是下载网页数据,为搜索引擎系统提供数据源。许多大型网络搜索引擎系统被称为基于Web数据的搜索引擎系统采集,如Google、百度等。这显示了网络爬虫系统在搜索引擎中的重要性。除了供用户阅读的文字信息外,网页还收录一些超链接信息。网络爬虫系统通过网页中的超链接信息不断获取网络上的其他网页。正是因为这个采集进程像爬虫或者蜘蛛一样在网络上漫游,所以才叫做网络爬虫系统或者网络蜘蛛系统,英文叫Spider或者Crawler。
2.2网络爬虫系统的工作原理
在网络爬虫的系统框架中,主要流程由控制器、解析器和资源库三部分组成。控制器的主要工作是为多个线程中的每个爬虫线程分配工作任务。解析器的主要工作是下载网页和处理页面,主要是处理一些JS脚本标签、CSS代码内容、空格字符、HTML标签等。爬虫的基本工作是由解析器完成的。资源库用于存储下载的网络资源。通常使用大型数据库,例如 Oracle 数据库来存储和索引它。
控制器
控制器是网络爬虫的中央控制器。主要负责根据系统发送的URL链接分配一个线程,然后启动线程调用爬虫爬取网页。
解析器
解析器负责网络爬虫的主要部分。它的主要任务是:下载网页的功能,处理网页的文本,如过滤,提取特殊的HTML标签,分析数据。
资源库
它主要是一个容器,用于存储从网页下载的数据记录,并为索引生成提供目标源。大中型数据库产品包括:Oracle、SqlServer等。
网络爬虫系统一般会选择一些比较重要的出度(网页中超链接数)网站较大的URL作为种子URL集。网络爬虫系统使用这些种子集作为初始 URL 来开始数据爬取。因为网页中收录链接信息,所以会通过已有网页的URL获取一些新的URL。网页之间的指向结构可以看作是一片森林。每个种子 URL 对应的网页是森林中一棵树的根节点。.
这样,网络爬虫系统就可以按照广度优先算法或深度优先算法遍历所有网页。由于深度优先搜索算法可能导致爬虫系统陷入网站内部,不利于搜索距离网站首页比较近的网页信息,因此广度优先搜索算法一般使用采集网页。网络爬虫系统首先将种子 URL 放入下载队列,然后简单地从队列头部获取一个 URL 来下载其对应的网页。获取网页内容并存储后,通过解析网页中的链接信息可以得到一些新的URL,并将这些URL加入到下载队列中。然后取出一个网址,下载其对应的网页,
网络爬虫的基本工作流程如下:
1.首先选择一个精心挑选的种子 URL 的子集;
2.将这些网址放入待抓取的网址队列中;
3. 从待爬取URL队列中取出待爬取的URL,解析DNS,获取主机IP,下载该URL对应的网页,存入下载的网页库中。此外,将这些 URL 放入 Crawl URLs 队列;
4.解析URL队列中已经爬取的URL,分析其中的其他URL,将URL放入待爬取的URL队列,从而进入下一个循环。
2.3 爬取策略
在爬虫系统中,待爬取的 URL 队列是一个重要的部分。待爬取的URL队列中的URL的排列顺序也是一个重要的问题,因为它涉及到先爬到哪个页面,再爬到哪个页面。确定这些 URL 排列顺序的方法称为爬取策略。下面重点介绍几种常见的爬取策略:
2.3.1 深度优先遍历策略
深度优先遍历策略是指网络爬虫会从起始页开始,一个接一个的链接,处理完该行再到下一个起始页,继续跟踪该链接。我们以下图为例:
遍历路径:AF-GE-H-IBCD
2.3.2 广度优先遍历策略
广度优先遍历的基本思想是将新下载的网页中找到的链接直接插入待爬取URL队列的末尾。也就是说,网络爬虫会先爬取起始网页链接的所有网页,然后选择其中一个链接的网页,继续爬取该网页链接的所有网页。或者以上图为例:
遍历路径:ABCDE-FGHI
2.3.3 反向链接策略
反向链接数是指从其他网页指向一个网页的链接数。反向链接的数量表示网页内容被他人推荐的程度。因此,在很多情况下,搜索引擎的爬取系统会使用这个指标来评估网页的重要性,从而确定不同网页的爬取顺序。
在真实的网络环境中,由于广告链接和作弊链接的存在,反向链接的数量并不能完全等同于他人的重要性。因此,搜索引擎倾向于考虑一些可靠的反向链接计数。
2.3.4PartialPageRank 策略
PartialPageRank算法借鉴了PageRank算法的思想:对于下载的网页,连同待爬取的URL队列中的URL,形成一组网页,计算每个页面的PageRank值。计算完成后,计算待爬取的URL队列中的URL。按 PageRank 值排序并按该顺序抓取页面。
如果每次爬取一个页面都重新计算一次PageRank值,一个折中的方案是每次爬取K个页面都重新计算一次PageRank值。但是这种情况还是有一个问题:对于下载页面中分析的链接,也就是我们前面提到的那部分未知网页,暂时没有PageRank值。为了解决这个问题,给这些页面一个临时的PageRank值:把这个网页的所有传入链接传入的PageRank值聚合起来,从而形成未知页面的PageRank值,从而参与排序.
2.3.5OPICStrategy
该算法实际上为页面分配了一个重要性分数。在算法开始之前,所有页面都会获得相同的初始现金。当某个页面P被下载时,P的现金分配给从P分析的所有链接,P的现金被清空。根据现金数量对待爬取URL队列中的所有页面进行排序。
2.3.六大网站优先策略
所有待爬取的URL队列中的网页都按照它们所属的网站进行分类。网站需要下载的页面较多,请先下载。这种策略也称为大站点优先策略。
3、爬虫分类
我应该选择 Nutch、Crawler4j、WebMagic、scrapy、WebCollector 还是其他来开发网络爬虫?上面提到的爬虫类,基本上可以分为三类:
(1)分布式爬虫:Nutch
(2)JAVA 爬虫:Crawler4j、WebMagic、WebCollector
(3)非JAVA爬虫:scrapy(基于Python语言开发)
3.1 分布式爬虫
爬虫使用分布式,主要解决两个问题:
1)海量网址管理
2)网速
现在比较流行的分布式爬虫是Apache的Nutch。但是对于大多数用户来说,Nutch 是这些爬虫中最差的选择,原因如下:
1)Nutch 是为搜索引擎设计的爬虫。大多数用户需要一个爬虫来进行准确的数据爬取(精细提取)。Nutch 运行的三分之二的流程是为搜索引擎设计的。提取意义不大。换句话说,使用 Nutch 进行数据提取会在不必要的计算上浪费大量时间。而如果你试图通过Nutch的二次开发使其适合提取业务,你基本上会破坏Nutch的框架,将Nutch改得面目全非,并且有能力修改Nutch,还不如自己写一个新的. 分布式爬虫框架。
2)Nutch 依赖hadoop 运行,hadoop 本身消耗大量时间。如果集群机器数量少,爬取速度不如单机爬虫快。
3)虽然Nutch有一套插件机制,但还是作为亮点来宣传的。可以看到一些开源的Nutch插件,提供精准提取功能。但是任何开发过 Nutch 插件的人都知道 Nutch 的插件系统有多糟糕。使用反射机制加载和调用插件,使得程序的编写和调试变得异常困难,更不用说在其上开发复杂的提取系统了。并且 Nutch 没有提供对应的插件挂载点进行精细提取。Nutch的插件只有五六个挂载点,而这五六个挂载点都是给搜索引擎服务的,不提供细提取的挂载点。Nutch 的大部分精炼提取插件都挂载在“页面解析”(parser)挂载点上。这个挂载点其实是用来解析链接(为后续爬取提供URL)和提供一些搜索引擎的。易于提取的网页信息(元信息、网页文本)。
4)使用Nutch进行爬虫的二次开发,编写和调试爬虫所需的时间往往是单机爬虫所需时间的十倍以上。学习 Nutch 源码的成本非常高,更何况团队中的每个人都必须了解 Nutch 源码。在调试过程中,会出现程序本身以外的各种问题(hadoop问题、hbase问题)。
5)很多人说Nutch2有gora,可以将数据持久化到avro文件、hbase、mysql等,其实很多人都误解了。这里所说的持久化数据是指在avro、hbase、mysql中存储URL信息(URL管理所需的数据)。不是您要提取的结构化数据。事实上,对于大多数人来说,URL 信息存在于何处并不重要。
6)Nutch2 的版本目前不适合开发。Nutch的官方稳定版是nutch2.2.1,但是这个版本绑定了gora-0.3。如果要使用hbase和nutch(大多数人使用nutch2是为了使用hbase),只能使用版本0.90左右的hbase,相应地,将hadoop版本降低到hadoop0.左右@>2。而且nutch2的官方教程也颇具误导性。Nutch2的教程有两个,分别是Nutch1.x和Nutch2.x。Nutch2.x官网是为了支持hbase0.94而写的。但其实这个Nutch2.x是指Nutch2.3之前和Nutch2.2.1之后的一个版本,在官方SVN中不断更新。而且它'
所以,如果你不是搜索引擎,尽量不要选择 Nutch 作为爬虫。一些团队喜欢跟风。他们坚持选择Nutch来开发精制履带。事实上,这是针对Nutch的声誉。当然,最终的结果往往是项目延期。
如果你在做搜索引擎,Nutch1.x 是一个非常不错的选择。Nutch1.x 和 solr 或 es 可以组成一个非常强大的搜索引擎。如果必须使用 Nutch2,建议等到 Nutch2.3 发布。当前的 Nutch2 是一个非常不稳定的版本。
分布式爬虫平台架构图
3.2JAVA爬虫
在这里,将JAVA爬虫划分为一个单独的类别,因为JAVA在网络爬虫的生态系统中非常完善。相关资料也是最全的。这里可能有争议,我只是随便说说。
其实开源网络爬虫(框架)的开发非常简单,前人已经解决了困难和复杂的问题(如DOM树解析定位、字符集检测、海量URL去重等),可以据说没有技术含量。. 包括Nutch,其实Nutch的技术难点就是开发hadoop,代码本身也很简单。从某种意义上说,网络爬虫类似于遍历本机的文件以查找文件中的信息。没有任何困难。选择开源爬虫框架的原因是为了省事。比如爬虫的URL管理、线程池等模块,任何人都可以做,但是需要一段时间的调试和修改才能稳定下来。
对于爬虫的功能。用户比较关心的问题往往是:
1)爬虫是否支持多线程,爬虫可以使用代理,爬虫可以抓取重复数据,爬虫可以抓取JS生成的信息吗?
不支持多线程、不支持代理、不能过滤重复URL的不叫开源爬虫,叫循环执行http请求。
js生成的信息能否被爬取与爬虫本身关系不大。爬虫主要负责遍历网站和下载页面。爬取js产生的信息与网页信息提取模块有关,往往需要模拟浏览器(htmlunit、selenium)来完成。这些模拟浏览器通常需要花费大量时间来处理一个页面。因此,一种策略是利用这些爬虫遍历网站,当遇到需要解析的页面时,将网页的相关信息提交给模拟浏览器,完成对JS生成信息的提取。
2)爬虫可以抓取ajax信息吗?
网页上有一些异步加载的数据。爬取数据有两种方式:使用模拟浏览器(问题1中描述),或者分析ajax的http请求,自己生成ajax请求的url,获取返回的数据。如果你自己生成ajax请求,那么使用开源爬虫有什么意义呢?其实就是利用开源爬虫的线程池和URL管理功能(比如断点爬取)。
如果我已经可以生成我需要的ajax请求(列表),我该如何使用这些爬虫来爬取这些请求呢?
爬虫往往被设计成广度遍历或深度遍历的方式来遍历静态或动态页面。爬取ajax信息属于deepweb(深网)的范畴,虽然大部分爬虫并不直接支持。但它也可以通过某些方式完成。例如,WebCollector 使用广度遍历来遍历 网站。爬虫的第一轮爬取就是爬取种子集(seeds)中的所有url。简单来说就是将生成的ajax请求作为种子,放入爬虫中。使用爬虫对这些种子进行深度为 1 的广度遍历(默认为广度遍历)。
3)爬虫如何爬取待登录的网站?
这些开源爬虫都支持在爬取时指定cookies,而模拟登录主要依赖cookies。至于如何获取cookies,就不是爬虫管理的问题了。您可以手动获取cookies,使用http请求模拟登录,或者使用模拟浏览器自动登录。
4)爬虫如何从网页中提取信息?
开源爬虫一般会集成网页提取工具。主要支持两种规范:CSSSELECTOR 和 XPATH。至于哪个更好,我这里就不评论了。
5)爬虫是如何保存网页信息的?
有一些爬虫带有一个负责持久性的模块。例如,webmagic 有一个名为 pipeline 的模块。通过简单的配置,爬虫提取的信息可以持久化到文件、数据库等。还有一些爬虫不直接为用户提供数据持久化模块。比如 crawler4j 和 webcollector。让用户在网页处理模块中添加提交数据库的操作。至于用管道模块好不好,就类似于用ORM操作数据库好不好的问题,看你的业务。
6)爬虫被网站拦截了怎么办?
爬虫被网站阻塞,可以通过使用多个代理(随机代理)来解决。但是这些开源爬虫一般不直接支持随机代理的切换。因此,用户经常需要将获取到的agent放入一个全局数组中,并编写一段代码让agent随机获取(从数组中)。
7)网页可以调用爬虫吗?
爬虫的调用是在Web的服务器端调用的。您可以按照平时使用的方式使用它。可以使用这些爬虫。
8)爬虫速度怎么样?
单机开源爬虫的速度基本可以用到本地网速的极限。爬虫速度慢往往是因为用户减少了线程数,网速慢,或者数据持久化时与数据库的交互慢。而这些东西往往是由用户的机器和二次开发的代码决定的。这些开源爬虫的速度非常好。
9) 明明代码写对了,但是数据爬不出来。爬虫有问题吗?不同的爬虫可以解决吗?
如果代码写得正确,无法爬取数据,其他爬虫也将无法爬取。在这种情况下,要么是 网站 阻止了您,要么您抓取的数据是由 javascript 生成的。如果无法爬取数据,则无法通过更改爬虫来解决。
10)哪个爬虫可以判断网站是否已经爬完,哪个爬虫可以根据主题爬取?
爬虫无法判断网站是否已经爬完,只能尽量覆盖。
至于根据主题爬,爬虫把内容爬下来后就知道主题是什么了。因此,通常是整体爬下来,然后对内容进行过滤。如果爬取的范围太广,可以通过限制 URL 正则化来缩小范围。
11)哪个爬虫的设计模式和架构比较好?
设计模式是胡说八道。都说软件设计模式不错,软件开发后总结了几种设计模式。设计模式对软件开发没有指导意义。使用设计模式设计爬虫只会让爬虫的设计更加臃肿。
至于架构,目前开源爬虫主要是设计详细的数据结构,比如爬取线程池、任务队列等,大家都可以控制。爬虫的业务太简单了,用任何框架都谈不上。
所以对于 JAVA 开源爬虫,我认为,只要找到一个运行良好的。如果业务复杂,使用哪个爬虫,只能通过复杂的二次开发来满足需求。
3.3 非JAVA爬虫
在非JAVA语言编写的爬虫中,不乏优秀的爬虫。这里提取为一个类别,不是为了讨论爬虫本身的好坏,而是为了讨论larbin、scrapy等爬虫对开发成本的影响。
先说python爬虫,python用30行代码就可以完成JAVA50行代码的任务。Python写代码确实很快,但是在调试代码阶段,调试python代码所消耗的时间往往比编码阶段节省的时间要多得多。使用python开发,为了保证程序的正确性和稳定性,需要编写更多的测试模块。当然,如果爬取规模不大,爬取业务也不复杂,用scrapy还是不错的,可以轻松完成爬取任务。
上图是Scrapy的架构图。绿线是数据流。从初始 URL 开始,Scheduler 会将其交给 Downloader 进行下载。下载完成后交给Spider进行分析,将要保存的数据发送到ItemPipeline。那就是对数据进行后处理。此外,可以在数据流通道中安装各种中间件,进行必要的处理。因此,在开发爬虫时,最好先规划好各个模块。我的做法是分别规划下载模块、爬取模块、调度模块、数据存储模块。
对于C++爬虫来说,学习成本会比较大。而且不能只计算一个人的学习成本。如果软件需要一个团队来开发或者移交,那就是很多人的学习成本。软件调试不是那么容易。
还有一些ruby和php爬虫,这里就不多评价了。确实有一些非常小的data采集任务,在ruby或者php中都用得上。但是,要选择这些语言的开源爬虫,一方面需要调查相关的生态系统,另一方面,这些开源爬虫可能存在一些你找不到的bug(很少有人使用它们,而且信息也较少)
4、反爬虫技术
由于搜索引擎的普及,网络爬虫已经成为一种非常流行的网络技术。除了专注于搜索的谷歌、雅虎、微软和百度之外,几乎每个大型门户网站网站都有自己的搜索引擎,大大小小的。可以叫的名字有几十种,不知道的种类有上万种。对于一个内容驱动的网站,难免会被网络爬虫光顾。
一些智能搜索引擎爬虫的爬取频率比较合理,资源消耗也比较小,但是很多不良网络爬虫对网页的爬取能力很差,经常循环重复上百个请求。拿,这种爬虫对中小型网站来说往往是毁灭性的打击,尤其是一些缺乏爬虫编写经验的程序员编写的爬虫,破坏性极大,导致网站访问压力会很大非常大,这将导致 网站 访问缓慢甚至无法访问。
一般网站反爬虫从三个方面进行:用户请求的头文件、用户行为、网站目录和数据加载方式。前两种比较容易遇到,从这些角度来看,大部分网站都是反爬虫。会使用第三种使用ajax的网站,增加了爬取的难度。
4.1 反爬虫通过Headers
反爬取用户请求的头部是最常见的反爬取策略。很多网站会检测header的User-Agent,有的网站会检测Referer(有些资源的防盗链网站就是检测Referer)。如果遇到这样的反爬虫机制,可以直接在爬虫中添加Headers,将浏览器的User-Agent复制到爬虫的Headers中;或者将Referer值改为目标网站域名。对于检测Headers的反爬虫,在爬虫中修改或添加Headers可以很好的绕过。
[评论:它通常很容易被忽略。通过对请求的抓包分析,确定referer,并添加到程序中模拟访问请求的header]
4.2 基于用户行为的反爬虫
网站的另一部分是检测用户行为,比如同一个IP在短时间内多次访问同一个页面,或者同一个账号在短时间内多次执行相同的操作。 查看全部
htmlunit抓取动态网页(中小微公司网络爬虫技术总结及解决办法(一))
网络爬虫技术总结
对于大数据行业来说,数据的价值不言而喻。在这个信息爆炸的时代,互联网上的信息数据太多了。对于中小微企业来说,合理使用爬虫爬取有价值的数据,是为了弥补自身先天的数据短缺。板子的最佳选择,本文主要从爬虫原理、架构、分类和反爬虫技术方面总结了爬虫技术。
1、爬虫技术概述
网络爬虫是一种程序或脚本,它根据一定的规则自动爬取万维网上的信息。它们广泛应用于互联网搜索引擎或其他类似的网站,并且可以自动采集所有它可以访问的页面的内容来获取或更新这些网站的内容和检索方式. 从功能上来说,爬虫一般分为数据采集、处理、存储三部分。
传统爬虫从一个或多个初始网页的URL开始,获取初始网页上的URL。在对网页进行爬取的过程中,不断地从当前页面中提取新的 URL 并放入队列中,直到满足系统的某些停止条件。焦点爬虫的工作流程比较复杂。它需要按照一定的网页分析算法过滤掉与主题无关的链接,保留有用的链接,并放入等待抓取的URL队列中。然后,它会根据一定的搜索策略从队列中选择下一个要爬取的网页URL,并重复上述过程,直到达到系统的一定条件并停止。另外,爬虫爬取的所有网页都会被系统存储,进行一定的分析、过滤和索引,以供后续查询和检索;对于重点爬虫来说,这个过程中得到的分析结果也可能对后续的爬取过程给出反馈和指导。
与通用网络爬虫相比,聚焦爬虫还需要解决三个主要问题:
(1)爬取目标的描述或定义;
(2)网页或数据的分析和过滤;
(3)URL 的搜索策略。
2、爬虫原理
2.1网络爬虫原理
网络爬虫系统的功能是下载网页数据,为搜索引擎系统提供数据源。许多大型网络搜索引擎系统被称为基于Web数据的搜索引擎系统采集,如Google、百度等。这显示了网络爬虫系统在搜索引擎中的重要性。除了供用户阅读的文字信息外,网页还收录一些超链接信息。网络爬虫系统通过网页中的超链接信息不断获取网络上的其他网页。正是因为这个采集进程像爬虫或者蜘蛛一样在网络上漫游,所以才叫做网络爬虫系统或者网络蜘蛛系统,英文叫Spider或者Crawler。
2.2网络爬虫系统的工作原理
在网络爬虫的系统框架中,主要流程由控制器、解析器和资源库三部分组成。控制器的主要工作是为多个线程中的每个爬虫线程分配工作任务。解析器的主要工作是下载网页和处理页面,主要是处理一些JS脚本标签、CSS代码内容、空格字符、HTML标签等。爬虫的基本工作是由解析器完成的。资源库用于存储下载的网络资源。通常使用大型数据库,例如 Oracle 数据库来存储和索引它。
控制器
控制器是网络爬虫的中央控制器。主要负责根据系统发送的URL链接分配一个线程,然后启动线程调用爬虫爬取网页。
解析器
解析器负责网络爬虫的主要部分。它的主要任务是:下载网页的功能,处理网页的文本,如过滤,提取特殊的HTML标签,分析数据。
资源库
它主要是一个容器,用于存储从网页下载的数据记录,并为索引生成提供目标源。大中型数据库产品包括:Oracle、SqlServer等。
网络爬虫系统一般会选择一些比较重要的出度(网页中超链接数)网站较大的URL作为种子URL集。网络爬虫系统使用这些种子集作为初始 URL 来开始数据爬取。因为网页中收录链接信息,所以会通过已有网页的URL获取一些新的URL。网页之间的指向结构可以看作是一片森林。每个种子 URL 对应的网页是森林中一棵树的根节点。.
这样,网络爬虫系统就可以按照广度优先算法或深度优先算法遍历所有网页。由于深度优先搜索算法可能导致爬虫系统陷入网站内部,不利于搜索距离网站首页比较近的网页信息,因此广度优先搜索算法一般使用采集网页。网络爬虫系统首先将种子 URL 放入下载队列,然后简单地从队列头部获取一个 URL 来下载其对应的网页。获取网页内容并存储后,通过解析网页中的链接信息可以得到一些新的URL,并将这些URL加入到下载队列中。然后取出一个网址,下载其对应的网页,
网络爬虫的基本工作流程如下:
1.首先选择一个精心挑选的种子 URL 的子集;
2.将这些网址放入待抓取的网址队列中;
3. 从待爬取URL队列中取出待爬取的URL,解析DNS,获取主机IP,下载该URL对应的网页,存入下载的网页库中。此外,将这些 URL 放入 Crawl URLs 队列;
4.解析URL队列中已经爬取的URL,分析其中的其他URL,将URL放入待爬取的URL队列,从而进入下一个循环。
2.3 爬取策略
在爬虫系统中,待爬取的 URL 队列是一个重要的部分。待爬取的URL队列中的URL的排列顺序也是一个重要的问题,因为它涉及到先爬到哪个页面,再爬到哪个页面。确定这些 URL 排列顺序的方法称为爬取策略。下面重点介绍几种常见的爬取策略:
2.3.1 深度优先遍历策略
深度优先遍历策略是指网络爬虫会从起始页开始,一个接一个的链接,处理完该行再到下一个起始页,继续跟踪该链接。我们以下图为例:
遍历路径:AF-GE-H-IBCD
2.3.2 广度优先遍历策略
广度优先遍历的基本思想是将新下载的网页中找到的链接直接插入待爬取URL队列的末尾。也就是说,网络爬虫会先爬取起始网页链接的所有网页,然后选择其中一个链接的网页,继续爬取该网页链接的所有网页。或者以上图为例:
遍历路径:ABCDE-FGHI
2.3.3 反向链接策略
反向链接数是指从其他网页指向一个网页的链接数。反向链接的数量表示网页内容被他人推荐的程度。因此,在很多情况下,搜索引擎的爬取系统会使用这个指标来评估网页的重要性,从而确定不同网页的爬取顺序。
在真实的网络环境中,由于广告链接和作弊链接的存在,反向链接的数量并不能完全等同于他人的重要性。因此,搜索引擎倾向于考虑一些可靠的反向链接计数。
2.3.4PartialPageRank 策略
PartialPageRank算法借鉴了PageRank算法的思想:对于下载的网页,连同待爬取的URL队列中的URL,形成一组网页,计算每个页面的PageRank值。计算完成后,计算待爬取的URL队列中的URL。按 PageRank 值排序并按该顺序抓取页面。
如果每次爬取一个页面都重新计算一次PageRank值,一个折中的方案是每次爬取K个页面都重新计算一次PageRank值。但是这种情况还是有一个问题:对于下载页面中分析的链接,也就是我们前面提到的那部分未知网页,暂时没有PageRank值。为了解决这个问题,给这些页面一个临时的PageRank值:把这个网页的所有传入链接传入的PageRank值聚合起来,从而形成未知页面的PageRank值,从而参与排序.
2.3.5OPICStrategy
该算法实际上为页面分配了一个重要性分数。在算法开始之前,所有页面都会获得相同的初始现金。当某个页面P被下载时,P的现金分配给从P分析的所有链接,P的现金被清空。根据现金数量对待爬取URL队列中的所有页面进行排序。
2.3.六大网站优先策略
所有待爬取的URL队列中的网页都按照它们所属的网站进行分类。网站需要下载的页面较多,请先下载。这种策略也称为大站点优先策略。
3、爬虫分类
我应该选择 Nutch、Crawler4j、WebMagic、scrapy、WebCollector 还是其他来开发网络爬虫?上面提到的爬虫类,基本上可以分为三类:
(1)分布式爬虫:Nutch
(2)JAVA 爬虫:Crawler4j、WebMagic、WebCollector
(3)非JAVA爬虫:scrapy(基于Python语言开发)
3.1 分布式爬虫
爬虫使用分布式,主要解决两个问题:
1)海量网址管理
2)网速
现在比较流行的分布式爬虫是Apache的Nutch。但是对于大多数用户来说,Nutch 是这些爬虫中最差的选择,原因如下:
1)Nutch 是为搜索引擎设计的爬虫。大多数用户需要一个爬虫来进行准确的数据爬取(精细提取)。Nutch 运行的三分之二的流程是为搜索引擎设计的。提取意义不大。换句话说,使用 Nutch 进行数据提取会在不必要的计算上浪费大量时间。而如果你试图通过Nutch的二次开发使其适合提取业务,你基本上会破坏Nutch的框架,将Nutch改得面目全非,并且有能力修改Nutch,还不如自己写一个新的. 分布式爬虫框架。
2)Nutch 依赖hadoop 运行,hadoop 本身消耗大量时间。如果集群机器数量少,爬取速度不如单机爬虫快。
3)虽然Nutch有一套插件机制,但还是作为亮点来宣传的。可以看到一些开源的Nutch插件,提供精准提取功能。但是任何开发过 Nutch 插件的人都知道 Nutch 的插件系统有多糟糕。使用反射机制加载和调用插件,使得程序的编写和调试变得异常困难,更不用说在其上开发复杂的提取系统了。并且 Nutch 没有提供对应的插件挂载点进行精细提取。Nutch的插件只有五六个挂载点,而这五六个挂载点都是给搜索引擎服务的,不提供细提取的挂载点。Nutch 的大部分精炼提取插件都挂载在“页面解析”(parser)挂载点上。这个挂载点其实是用来解析链接(为后续爬取提供URL)和提供一些搜索引擎的。易于提取的网页信息(元信息、网页文本)。
4)使用Nutch进行爬虫的二次开发,编写和调试爬虫所需的时间往往是单机爬虫所需时间的十倍以上。学习 Nutch 源码的成本非常高,更何况团队中的每个人都必须了解 Nutch 源码。在调试过程中,会出现程序本身以外的各种问题(hadoop问题、hbase问题)。
5)很多人说Nutch2有gora,可以将数据持久化到avro文件、hbase、mysql等,其实很多人都误解了。这里所说的持久化数据是指在avro、hbase、mysql中存储URL信息(URL管理所需的数据)。不是您要提取的结构化数据。事实上,对于大多数人来说,URL 信息存在于何处并不重要。
6)Nutch2 的版本目前不适合开发。Nutch的官方稳定版是nutch2.2.1,但是这个版本绑定了gora-0.3。如果要使用hbase和nutch(大多数人使用nutch2是为了使用hbase),只能使用版本0.90左右的hbase,相应地,将hadoop版本降低到hadoop0.左右@>2。而且nutch2的官方教程也颇具误导性。Nutch2的教程有两个,分别是Nutch1.x和Nutch2.x。Nutch2.x官网是为了支持hbase0.94而写的。但其实这个Nutch2.x是指Nutch2.3之前和Nutch2.2.1之后的一个版本,在官方SVN中不断更新。而且它'
所以,如果你不是搜索引擎,尽量不要选择 Nutch 作为爬虫。一些团队喜欢跟风。他们坚持选择Nutch来开发精制履带。事实上,这是针对Nutch的声誉。当然,最终的结果往往是项目延期。
如果你在做搜索引擎,Nutch1.x 是一个非常不错的选择。Nutch1.x 和 solr 或 es 可以组成一个非常强大的搜索引擎。如果必须使用 Nutch2,建议等到 Nutch2.3 发布。当前的 Nutch2 是一个非常不稳定的版本。
分布式爬虫平台架构图
3.2JAVA爬虫
在这里,将JAVA爬虫划分为一个单独的类别,因为JAVA在网络爬虫的生态系统中非常完善。相关资料也是最全的。这里可能有争议,我只是随便说说。
其实开源网络爬虫(框架)的开发非常简单,前人已经解决了困难和复杂的问题(如DOM树解析定位、字符集检测、海量URL去重等),可以据说没有技术含量。. 包括Nutch,其实Nutch的技术难点就是开发hadoop,代码本身也很简单。从某种意义上说,网络爬虫类似于遍历本机的文件以查找文件中的信息。没有任何困难。选择开源爬虫框架的原因是为了省事。比如爬虫的URL管理、线程池等模块,任何人都可以做,但是需要一段时间的调试和修改才能稳定下来。
对于爬虫的功能。用户比较关心的问题往往是:
1)爬虫是否支持多线程,爬虫可以使用代理,爬虫可以抓取重复数据,爬虫可以抓取JS生成的信息吗?
不支持多线程、不支持代理、不能过滤重复URL的不叫开源爬虫,叫循环执行http请求。
js生成的信息能否被爬取与爬虫本身关系不大。爬虫主要负责遍历网站和下载页面。爬取js产生的信息与网页信息提取模块有关,往往需要模拟浏览器(htmlunit、selenium)来完成。这些模拟浏览器通常需要花费大量时间来处理一个页面。因此,一种策略是利用这些爬虫遍历网站,当遇到需要解析的页面时,将网页的相关信息提交给模拟浏览器,完成对JS生成信息的提取。
2)爬虫可以抓取ajax信息吗?
网页上有一些异步加载的数据。爬取数据有两种方式:使用模拟浏览器(问题1中描述),或者分析ajax的http请求,自己生成ajax请求的url,获取返回的数据。如果你自己生成ajax请求,那么使用开源爬虫有什么意义呢?其实就是利用开源爬虫的线程池和URL管理功能(比如断点爬取)。
如果我已经可以生成我需要的ajax请求(列表),我该如何使用这些爬虫来爬取这些请求呢?
爬虫往往被设计成广度遍历或深度遍历的方式来遍历静态或动态页面。爬取ajax信息属于deepweb(深网)的范畴,虽然大部分爬虫并不直接支持。但它也可以通过某些方式完成。例如,WebCollector 使用广度遍历来遍历 网站。爬虫的第一轮爬取就是爬取种子集(seeds)中的所有url。简单来说就是将生成的ajax请求作为种子,放入爬虫中。使用爬虫对这些种子进行深度为 1 的广度遍历(默认为广度遍历)。
3)爬虫如何爬取待登录的网站?
这些开源爬虫都支持在爬取时指定cookies,而模拟登录主要依赖cookies。至于如何获取cookies,就不是爬虫管理的问题了。您可以手动获取cookies,使用http请求模拟登录,或者使用模拟浏览器自动登录。
4)爬虫如何从网页中提取信息?
开源爬虫一般会集成网页提取工具。主要支持两种规范:CSSSELECTOR 和 XPATH。至于哪个更好,我这里就不评论了。
5)爬虫是如何保存网页信息的?
有一些爬虫带有一个负责持久性的模块。例如,webmagic 有一个名为 pipeline 的模块。通过简单的配置,爬虫提取的信息可以持久化到文件、数据库等。还有一些爬虫不直接为用户提供数据持久化模块。比如 crawler4j 和 webcollector。让用户在网页处理模块中添加提交数据库的操作。至于用管道模块好不好,就类似于用ORM操作数据库好不好的问题,看你的业务。
6)爬虫被网站拦截了怎么办?
爬虫被网站阻塞,可以通过使用多个代理(随机代理)来解决。但是这些开源爬虫一般不直接支持随机代理的切换。因此,用户经常需要将获取到的agent放入一个全局数组中,并编写一段代码让agent随机获取(从数组中)。
7)网页可以调用爬虫吗?
爬虫的调用是在Web的服务器端调用的。您可以按照平时使用的方式使用它。可以使用这些爬虫。
8)爬虫速度怎么样?
单机开源爬虫的速度基本可以用到本地网速的极限。爬虫速度慢往往是因为用户减少了线程数,网速慢,或者数据持久化时与数据库的交互慢。而这些东西往往是由用户的机器和二次开发的代码决定的。这些开源爬虫的速度非常好。
9) 明明代码写对了,但是数据爬不出来。爬虫有问题吗?不同的爬虫可以解决吗?
如果代码写得正确,无法爬取数据,其他爬虫也将无法爬取。在这种情况下,要么是 网站 阻止了您,要么您抓取的数据是由 javascript 生成的。如果无法爬取数据,则无法通过更改爬虫来解决。
10)哪个爬虫可以判断网站是否已经爬完,哪个爬虫可以根据主题爬取?
爬虫无法判断网站是否已经爬完,只能尽量覆盖。
至于根据主题爬,爬虫把内容爬下来后就知道主题是什么了。因此,通常是整体爬下来,然后对内容进行过滤。如果爬取的范围太广,可以通过限制 URL 正则化来缩小范围。
11)哪个爬虫的设计模式和架构比较好?
设计模式是胡说八道。都说软件设计模式不错,软件开发后总结了几种设计模式。设计模式对软件开发没有指导意义。使用设计模式设计爬虫只会让爬虫的设计更加臃肿。
至于架构,目前开源爬虫主要是设计详细的数据结构,比如爬取线程池、任务队列等,大家都可以控制。爬虫的业务太简单了,用任何框架都谈不上。
所以对于 JAVA 开源爬虫,我认为,只要找到一个运行良好的。如果业务复杂,使用哪个爬虫,只能通过复杂的二次开发来满足需求。
3.3 非JAVA爬虫
在非JAVA语言编写的爬虫中,不乏优秀的爬虫。这里提取为一个类别,不是为了讨论爬虫本身的好坏,而是为了讨论larbin、scrapy等爬虫对开发成本的影响。
先说python爬虫,python用30行代码就可以完成JAVA50行代码的任务。Python写代码确实很快,但是在调试代码阶段,调试python代码所消耗的时间往往比编码阶段节省的时间要多得多。使用python开发,为了保证程序的正确性和稳定性,需要编写更多的测试模块。当然,如果爬取规模不大,爬取业务也不复杂,用scrapy还是不错的,可以轻松完成爬取任务。
上图是Scrapy的架构图。绿线是数据流。从初始 URL 开始,Scheduler 会将其交给 Downloader 进行下载。下载完成后交给Spider进行分析,将要保存的数据发送到ItemPipeline。那就是对数据进行后处理。此外,可以在数据流通道中安装各种中间件,进行必要的处理。因此,在开发爬虫时,最好先规划好各个模块。我的做法是分别规划下载模块、爬取模块、调度模块、数据存储模块。
对于C++爬虫来说,学习成本会比较大。而且不能只计算一个人的学习成本。如果软件需要一个团队来开发或者移交,那就是很多人的学习成本。软件调试不是那么容易。
还有一些ruby和php爬虫,这里就不多评价了。确实有一些非常小的data采集任务,在ruby或者php中都用得上。但是,要选择这些语言的开源爬虫,一方面需要调查相关的生态系统,另一方面,这些开源爬虫可能存在一些你找不到的bug(很少有人使用它们,而且信息也较少)
4、反爬虫技术
由于搜索引擎的普及,网络爬虫已经成为一种非常流行的网络技术。除了专注于搜索的谷歌、雅虎、微软和百度之外,几乎每个大型门户网站网站都有自己的搜索引擎,大大小小的。可以叫的名字有几十种,不知道的种类有上万种。对于一个内容驱动的网站,难免会被网络爬虫光顾。
一些智能搜索引擎爬虫的爬取频率比较合理,资源消耗也比较小,但是很多不良网络爬虫对网页的爬取能力很差,经常循环重复上百个请求。拿,这种爬虫对中小型网站来说往往是毁灭性的打击,尤其是一些缺乏爬虫编写经验的程序员编写的爬虫,破坏性极大,导致网站访问压力会很大非常大,这将导致 网站 访问缓慢甚至无法访问。
一般网站反爬虫从三个方面进行:用户请求的头文件、用户行为、网站目录和数据加载方式。前两种比较容易遇到,从这些角度来看,大部分网站都是反爬虫。会使用第三种使用ajax的网站,增加了爬取的难度。
4.1 反爬虫通过Headers
反爬取用户请求的头部是最常见的反爬取策略。很多网站会检测header的User-Agent,有的网站会检测Referer(有些资源的防盗链网站就是检测Referer)。如果遇到这样的反爬虫机制,可以直接在爬虫中添加Headers,将浏览器的User-Agent复制到爬虫的Headers中;或者将Referer值改为目标网站域名。对于检测Headers的反爬虫,在爬虫中修改或添加Headers可以很好的绕过。
[评论:它通常很容易被忽略。通过对请求的抓包分析,确定referer,并添加到程序中模拟访问请求的header]
4.2 基于用户行为的反爬虫
网站的另一部分是检测用户行为,比如同一个IP在短时间内多次访问同一个页面,或者同一个账号在短时间内多次执行相同的操作。
htmlunit抓取动态网页(Java爬取博客阅读文章最多)
网站优化 • 优采云 发表了文章 • 0 个评论 • 44 次浏览 • 2022-02-01 02:18
更新,这很尴尬,这个文章博客是阅读最多的文章,但也是最被践踏的。
爬取思路:
所谓动态是指通过请求后台可以动态改变对应的html页面,开始时页面并不是全部显示出来的。
大多数操作都是通过请求完成的,一个请求,一个返回。在大多数网页中,请求往往被开发者隐藏在 js 代码中。
所以将爬取动态网页的思路转化为找到对应的js代码并执行对应的js代码,从而通过java代码实现页面的动态变化。
而当页面能够正确显示的时候,我们就可以像爬静态网页一样爬取数据了!
首先,可以使用htmlunit来模拟鼠标点击事件,很容易实现:
/**
* 通过htmlunit来获得一些搜狗的网址。
* 通过模拟鼠标点击事件来实现
* @param key
* @return
* @throws Exception
*/
public String getNextUrl(String key){
String page = new String();
try {
WebClient webClient = new WebClient();
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(false);
//去拿网页
HtmlPage htmlPage = webClient.getPage("http://pic.sogou.com/");
//得到表单
HtmlForm form = htmlPage.getFormByName("searchForm");
//得到提交按钮
HtmlSubmitInput button = form.getInputByValue("搜狗搜索");
//得到输入框
HtmlTextInput textField = form.getInputByName("query");
//输入内容
textField.setValueAttribute(key);
//点一下按钮
HtmlPage nextPage = button.click();
String str = nextPage.toString();
page = cutString(str);
webClient.close();
} catch (Exception e) {
e.printStackTrace();
}
return page;
}
如上图,我只是通过java代码将关键字填入搜索我的,然后通过getInputByValue方法得到按钮控件,最后直接button.click(),
即可以模拟点击,将点击后返回的http请求解析成html页面。
这个功能其实很强大。比如你可以使用这个功能来模拟抢票,或者使用点击事件,加上搜索相关知识,将整个系统下线,并以html的形式保存。
接下来就是使用强大的htmlunit来执行js代码了。
先写一个简单的jsp页面:
Insert title here
原数字
function change(value) {
document.getElementById("test").innerHTML = value;
return "hello htmlUnit";
}
从上面可以看出,jsp页面很简单,只是一个函数变化,用来调用htmlUnit。
接下来是一个使用 htmlunit 的类。此类通过支持 JavaScript 解释器来工作,
然后将自己编写的JavaScript代码嵌入到页面中执行,获取执行后的返回结果返回页面。
package com.blog.anla;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class TestMyOwnPage {
private void action() {
WebClient webClient = new WebClient();
try {
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true); // 设置支持JavaScript。
// 去拿网页
HtmlPage htmlPage = webClient
.getPage("http://localhost:8989/testHtmlScrop/index.jsp");
String s = "更改后的数字";
ScriptResult t = htmlPage.executeJavaScript("change(\"" + s
+ "\");", "injected script", 500);
// 这里是在500行插入这一小行JavaScript代码段,因为如果在默认的1行,那不会有结果
// 因为js是顺序执行的,当你执行第一行js代码时,可能还没有渲染body里面的标签。
HtmlPage myPage = (HtmlPage) t.getNewPage();
String nextPage = myPage.asXml().toString();
String nextPage2 = myPage.asText().toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
webClient.close();
}
}
public static void main(String[] args) {
TestMyOwnPage tmop = new TestMyOwnPage();
tmop.action();
}
}
t.getNewPage()中有两个属性,一个是
javaScriptResult:执行这段代码后返回的结果,如果有(我上面写的,返回hello htmlunit),如果没有(返回Undefined)。
newPage_:执行此代码后返回的整个页面。
结果如下:
这段代码执行的最终结果如下:
asXml():将整个页面的html代码返回给我们:
而asText()只返回页面上可以显示的值,即head标签和label标签:
这种执行思路还可以动态执行相应的js代码,从而爬取需要的数据。
-------------------------------------------------- --------------------------------------2017 年 7 月更新---------- -------------------------------------- -------------------------------------------------- -----
这两天一直在做一个关于网络爬虫的系统
然而,当我开始攀爬时,我发现了一个问题。js的动态页面爬不下来。
网上找了很多方法,google也问了,主要是指htmlunit,下面是核心代码,
使用htmlunit的主要目的是模拟浏览器操作,因为有些链接点击无法直接通过src获取url,一般使用JavaScript。
简单拼接后的URL,所以用htmlunit直接模拟浏览器点击比较简单。
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true); //启用JS解释器,默认为true
webClient.getOptions().setCssEnabled(false); //禁用css支持
webClient.getOptions().setThrowExceptionOnScriptError(false); //js运行错误时,是否抛出异常
webClient.getOptions().setTimeout(20000);
HtmlPage page = wc.getPage("http://www.hao123.com");
//我认为这个最重要
String pageXml = page.asXml(); //以xml的形式获取响应文本
/**jsoup解析文档*/
Document doc = Jsoup.parse(pageXml, "http://cq.qq.com");
这个时候,就可以得到jsoup中的document对象了,接下来就好写了,就像爬普通静态网页一样了。
不过,webclient解析是还是会出现一些问题,js的问题,
主要是由于目标url的js写的有些问题,但在实际的浏览器中却会忽略,eclipse中会报异常。
今天看,好多人踩了,可能我当时没认真写博客吧。如果想找java爬虫项目,可以去我的专栏
图片搜索包括使用jsoup爬取图片,以及lire索引和搜索图片。
玫瑰会在你的手中留下挥之不去的芬芳。有什么问题可以多多讨论! 查看全部
htmlunit抓取动态网页(Java爬取博客阅读文章最多)
更新,这很尴尬,这个文章博客是阅读最多的文章,但也是最被践踏的。
爬取思路:
所谓动态是指通过请求后台可以动态改变对应的html页面,开始时页面并不是全部显示出来的。
大多数操作都是通过请求完成的,一个请求,一个返回。在大多数网页中,请求往往被开发者隐藏在 js 代码中。
所以将爬取动态网页的思路转化为找到对应的js代码并执行对应的js代码,从而通过java代码实现页面的动态变化。
而当页面能够正确显示的时候,我们就可以像爬静态网页一样爬取数据了!
首先,可以使用htmlunit来模拟鼠标点击事件,很容易实现:
/**
* 通过htmlunit来获得一些搜狗的网址。
* 通过模拟鼠标点击事件来实现
* @param key
* @return
* @throws Exception
*/
public String getNextUrl(String key){
String page = new String();
try {
WebClient webClient = new WebClient();
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(false);
//去拿网页
HtmlPage htmlPage = webClient.getPage("http://pic.sogou.com/");
//得到表单
HtmlForm form = htmlPage.getFormByName("searchForm");
//得到提交按钮
HtmlSubmitInput button = form.getInputByValue("搜狗搜索");
//得到输入框
HtmlTextInput textField = form.getInputByName("query");
//输入内容
textField.setValueAttribute(key);
//点一下按钮
HtmlPage nextPage = button.click();
String str = nextPage.toString();
page = cutString(str);
webClient.close();
} catch (Exception e) {
e.printStackTrace();
}
return page;
}
如上图,我只是通过java代码将关键字填入搜索我的,然后通过getInputByValue方法得到按钮控件,最后直接button.click(),
即可以模拟点击,将点击后返回的http请求解析成html页面。
这个功能其实很强大。比如你可以使用这个功能来模拟抢票,或者使用点击事件,加上搜索相关知识,将整个系统下线,并以html的形式保存。
接下来就是使用强大的htmlunit来执行js代码了。
先写一个简单的jsp页面:
Insert title here
原数字
function change(value) {
document.getElementById("test").innerHTML = value;
return "hello htmlUnit";
}
从上面可以看出,jsp页面很简单,只是一个函数变化,用来调用htmlUnit。
接下来是一个使用 htmlunit 的类。此类通过支持 JavaScript 解释器来工作,
然后将自己编写的JavaScript代码嵌入到页面中执行,获取执行后的返回结果返回页面。
package com.blog.anla;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class TestMyOwnPage {
private void action() {
WebClient webClient = new WebClient();
try {
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true); // 设置支持JavaScript。
// 去拿网页
HtmlPage htmlPage = webClient
.getPage("http://localhost:8989/testHtmlScrop/index.jsp");
String s = "更改后的数字";
ScriptResult t = htmlPage.executeJavaScript("change(\"" + s
+ "\");", "injected script", 500);
// 这里是在500行插入这一小行JavaScript代码段,因为如果在默认的1行,那不会有结果
// 因为js是顺序执行的,当你执行第一行js代码时,可能还没有渲染body里面的标签。
HtmlPage myPage = (HtmlPage) t.getNewPage();
String nextPage = myPage.asXml().toString();
String nextPage2 = myPage.asText().toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
webClient.close();
}
}
public static void main(String[] args) {
TestMyOwnPage tmop = new TestMyOwnPage();
tmop.action();
}
}
t.getNewPage()中有两个属性,一个是
javaScriptResult:执行这段代码后返回的结果,如果有(我上面写的,返回hello htmlunit),如果没有(返回Undefined)。
newPage_:执行此代码后返回的整个页面。
结果如下:
这段代码执行的最终结果如下:
asXml():将整个页面的html代码返回给我们:
而asText()只返回页面上可以显示的值,即head标签和label标签:
这种执行思路还可以动态执行相应的js代码,从而爬取需要的数据。
-------------------------------------------------- --------------------------------------2017 年 7 月更新---------- -------------------------------------- -------------------------------------------------- -----
这两天一直在做一个关于网络爬虫的系统
然而,当我开始攀爬时,我发现了一个问题。js的动态页面爬不下来。
网上找了很多方法,google也问了,主要是指htmlunit,下面是核心代码,
使用htmlunit的主要目的是模拟浏览器操作,因为有些链接点击无法直接通过src获取url,一般使用JavaScript。
简单拼接后的URL,所以用htmlunit直接模拟浏览器点击比较简单。
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true); //启用JS解释器,默认为true
webClient.getOptions().setCssEnabled(false); //禁用css支持
webClient.getOptions().setThrowExceptionOnScriptError(false); //js运行错误时,是否抛出异常
webClient.getOptions().setTimeout(20000);
HtmlPage page = wc.getPage("http://www.hao123.com");
//我认为这个最重要
String pageXml = page.asXml(); //以xml的形式获取响应文本
/**jsoup解析文档*/
Document doc = Jsoup.parse(pageXml, "http://cq.qq.com");
这个时候,就可以得到jsoup中的document对象了,接下来就好写了,就像爬普通静态网页一样了。
不过,webclient解析是还是会出现一些问题,js的问题,
主要是由于目标url的js写的有些问题,但在实际的浏览器中却会忽略,eclipse中会报异常。
今天看,好多人踩了,可能我当时没认真写博客吧。如果想找java爬虫项目,可以去我的专栏
图片搜索包括使用jsoup爬取图片,以及lire索引和搜索图片。
玫瑰会在你的手中留下挥之不去的芬芳。有什么问题可以多多讨论!
htmlunit抓取动态网页(所说的问题试试)
网站优化 • 优采云 发表了文章 • 0 个评论 • 58 次浏览 • 2022-01-30 07:11
没错,最后我还是用 Selenium 来实现我在上一篇文章中提到的问题。我没有尝试其他任何东西。我只试过火狐引擎。整体效果我还是可以接受的。
继续昨天的话题,既然要实现上一篇提到的问题,就需要一个可以执行js代码的框架。我的首选是htmlunit,先简单介绍一下htmlunit。以下段落摘自互联网。
htmlunit 是一个开源的java页面分析工具。启动htmlunit后,会在底层启动一个非界面浏览器。用户可以指定浏览器类型:firefox、ie等。如果不指定,默认使用INTERNET_EXPLORER_7:
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
只需调用:
HtmlPage 页面 = webClient.getPage(url);
可以获取页面的 HtmlPage 表示,然后通过:
InputStream 是 = targetPage.getWebResponse().getContentAsStream()
可以获取页面的输入流,从而获取页面的源代码,对于网络爬虫项目非常有用。
当然,你也可以从page中获取更多的页面元素。
重要的是,HtmlUnit 提供对执行 javascript 的支持:
page.executeJavaScript(javascript)
执行js后,返回一个ScriptResult对象,通过该对象可以获取执行js后的页面等信息。默认情况下,执行完js后,内部浏览器会进行页面跳转,跳转到执行完js后生成的新页面。如果js执行失败,则不会执行页面跳转。
最后可以通过page.executeJavaScript(javascript).getNewPage()获取执行的页面。也就是说,这里需要人为地执行javascript,这显然不符合我的初衷。另外,我的水平可能太差了。我在爬新浪新闻的页面时总是出错。根据网络上的查询结果,最可能的错误原因是htmlunit在执行一些带参数的请求时,由于参数顺序或者编码问题,请求失败,报错。关键是,运行它后我没有得到我需要的结果。
然后我寻找另一种解决方案。这时,我找到了 SeleniumWebDriver,这是我需要的解决方案。
参考资料和例子,就可以开始使用了。示例代码如下。
<p> 1 File pathToBinary = new File("D:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe");
2 FirefoxBinary ffBinary = new FirefoxBinary(pathToBinary);
3 FirefoxProfile firefoxProfile = new FirefoxProfile();
4 FirefoxDriver driver = new FirefoxDriver(ffBinary,firefoxProfile);
5
6
7 driver.get("http://cq.qq.com/baoliao/detail.htm?294064");
8
9 ArrayList list = new ArrayList();
10 list.add("http://www.sina.com.cn");
11 list.add("http://www.sohu.com");
12 list.add("http://www.163.com");
13 list.add("http://www.qq.com");
14
15 long start,end;
16
17 for(int i=0;i 查看全部
htmlunit抓取动态网页(所说的问题试试)
没错,最后我还是用 Selenium 来实现我在上一篇文章中提到的问题。我没有尝试其他任何东西。我只试过火狐引擎。整体效果我还是可以接受的。
继续昨天的话题,既然要实现上一篇提到的问题,就需要一个可以执行js代码的框架。我的首选是htmlunit,先简单介绍一下htmlunit。以下段落摘自互联网。
htmlunit 是一个开源的java页面分析工具。启动htmlunit后,会在底层启动一个非界面浏览器。用户可以指定浏览器类型:firefox、ie等。如果不指定,默认使用INTERNET_EXPLORER_7:
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
只需调用:
HtmlPage 页面 = webClient.getPage(url);
可以获取页面的 HtmlPage 表示,然后通过:
InputStream 是 = targetPage.getWebResponse().getContentAsStream()
可以获取页面的输入流,从而获取页面的源代码,对于网络爬虫项目非常有用。
当然,你也可以从page中获取更多的页面元素。
重要的是,HtmlUnit 提供对执行 javascript 的支持:
page.executeJavaScript(javascript)
执行js后,返回一个ScriptResult对象,通过该对象可以获取执行js后的页面等信息。默认情况下,执行完js后,内部浏览器会进行页面跳转,跳转到执行完js后生成的新页面。如果js执行失败,则不会执行页面跳转。
最后可以通过page.executeJavaScript(javascript).getNewPage()获取执行的页面。也就是说,这里需要人为地执行javascript,这显然不符合我的初衷。另外,我的水平可能太差了。我在爬新浪新闻的页面时总是出错。根据网络上的查询结果,最可能的错误原因是htmlunit在执行一些带参数的请求时,由于参数顺序或者编码问题,请求失败,报错。关键是,运行它后我没有得到我需要的结果。
然后我寻找另一种解决方案。这时,我找到了 SeleniumWebDriver,这是我需要的解决方案。
参考资料和例子,就可以开始使用了。示例代码如下。
<p> 1 File pathToBinary = new File("D:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe");
2 FirefoxBinary ffBinary = new FirefoxBinary(pathToBinary);
3 FirefoxProfile firefoxProfile = new FirefoxProfile();
4 FirefoxDriver driver = new FirefoxDriver(ffBinary,firefoxProfile);
5
6
7 driver.get("http://cq.qq.com/baoliao/detail.htm?294064");
8
9 ArrayList list = new ArrayList();
10 list.add("http://www.sina.com.cn");
11 list.add("http://www.sohu.com");
12 list.add("http://www.163.com");
13 list.add("http://www.qq.com");
14
15 long start,end;
16
17 for(int i=0;i
htmlunit抓取动态网页(1.HtmlUnit中文文档获取页面中特定的元素tips:1.)
网站优化 • 优采云 发表了文章 • 0 个评论 • 128 次浏览 • 2022-01-30 06:12
1.HtmlUnit 简介
HtmlUnit 是一个 java 无界面浏览器库。它模拟 HTML 文档并提供相应的 API,允许您调用页面、填写表单、单击链接等,就像您在“普通”浏览器中所做的那样。它具有相当不错的 JavaScript 支持(仍在改进),甚至能够处理相当复杂的 AJAX 库,根据使用的配置模拟 Chrome、Firefox 或 Internet Explorer。它通常用于测试目的或从 网站 检索信息。
HtmlUnit 不是一个通用的单元测试框架。它是一种模拟浏览器以进行测试的方法,旨在用于其他测试框架,例如 JUnit 或 TestNG。有关介绍,请参见文档“HtmlUnit 入门”。HtmlUnit 用作不同的开源工具,如 Canoo WebTest、JWebUnit、WebDriver、JSFUnit、WETATOR、Celerity、Spring MVC Test HtmlUnit 作为底层“浏览器”。
HtmlUnit 最初由 Gargoyle Software 的 Mike Bowler 编写,并在 Apache 2 许可下发布。从那时起,它收到了许多其他开发者的贡献,今天将得到他们的帮助。
几年前,我在为购物网站 做数据采集工作时偶然发现了HtmlUnit。记得当时页面上的价格数据是抓不到的,httpfox也无法追踪到价格数据的url。就在我手足无措的时候,HtmlUnit出现了,帮我解决了问题。所以今天我要说声谢谢并向大家推荐HtmlUnit。
2.htmlUnit 中文文档
3.1 获取页面的TITLE、XML代码、文本
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//创建一个webclient
WebClient webClient = new WebClient();
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
//获取页面
HtmlPage page = webClient.getPage("http://www.baidu.com/");
//获取页面的TITLE
str = page.getTitleText();
System.out.println(str);
//获取页面的XML代码
str = page.asXml();
System.out.println(str);
//获取页面的文本
str = page.asText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}
3.2 用不同版本的浏览器打开
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//使用FireFox读取网页
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = webClient.getPage("http://www.baidu.com/");
str = page.getTitleText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}
3.3 在页面中查找特定元素
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//通过id获得"百度一下"按钮
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
System.out.println(btn.getDefaultValue());
//关闭webclient
webClient.closeAllWindows();
}
}
提示:有些元素没有 id 和 name 或其他节点。您可以通过查找其子节点和父节点之间的规律性来获取该元素。具体方法请参考:
它的核心代码是:
final HtmlPage nextPage = ((DomElement)(htmlpage.getElementByName("key").getParentNode().getParentNode())).getLastElementChild().click();
3.4 元素检索
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//查找所有div
List hbList = page.getByXPath("//div");
HtmlDivision hb = (HtmlDivision)hbList.get(0);
System.out.println(hb.toString());
//查找并获取特定input
List inputList = page.getByXPath("//input[@id='su']");
HtmlInput input = (HtmlInput)inputList.get(0);
System.out.println(input.toString());
//关闭webclient
webClient.closeAllWindows();
}
}
3.5 提交搜索
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//获取搜索输入框并提交搜索内容
HtmlInput input = (HtmlInput)page.getHtmlElementById("kw");
System.out.println(input.toString());
input.setValueAttribute("ymd");
System.out.println(input.toString());
//获取搜索按钮并点击
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
HtmlPage page2 = btn.click();
//输出新页面的文本
System.out.println(page2.asText());
}
}
3.htmlUnit方法介绍
一、环境介绍
因为我是在自己的spring boot项目中引入的,所以只需要在pom文件中添加依赖即可
net.sourceforge.htmlunit
htmlunit
2.41.0
如果只是爬一点js 网站 建议改一下下面的依赖
net.sourceforge.htmlunit
htmlunit
2.23
两者的区别将在后面讨论。当然,如果你用的不是maven项目(没有pom),可以去官网下载源码库
二、使用
HtmlUnit 使用起来非常简单。使用的时候可以去官网手册查看语法。其实说明书只是介绍,下面听我说就够了;
1、创建客户端并配置客户端
final String url ="https:****";//大家这可以填自己爬虫的地址
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_68);//创建火狐浏览器 2.23版本是FIREFOX_45 new不写参数是默认浏览器
webClient.getOptions().setCssEnabled(false);//(屏蔽)css 因为css并不影响我们抓取数据 反而影响网页渲染效率
webClient.getOptions().setThrowExceptionOnScriptError(false);//(屏蔽)异常
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//(屏蔽)日志
webClient.getOptions().setJavaScriptEnabled(true);//加载js脚本
webClient.getOptions().setTimeout(50000);//设置超时时间
webClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置ajax
HtmlPage htmlPage = webClient.getPage(url);//将客户端获取的树形结构转化为HtmlPage
Thread.sleep(10000);//主线程休眠10秒 让客户端有时间执行js代码 也可以写成webClient.waitForBackgroundJavaScript(1000)
有一个等待js执行,2.41.0非常兼容很多js,但是2.3总是有问题不能刷新网页,2. 41.0 打印也很详细,执行过程比较慢,可能是慢而细致。
远程地址页差不多就到这里了。我们现在要做的就是解析dom节点并填写数据来模拟点击等事件。如果要打印出来 htmlPage.asText() 输出 htmlPage 节点的文本 htmlPage.asXml() 输出 htmlPage 节点的 xml 代码
2、节点获取
在这个链接中,建议准备一点前端知识
HtmlUnit 提供了两种获取节点的方法
XPath 查询:
更详细的xpath解释:
final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
//get list of all divs
final List divs = htmlPage .getByXPath("//div");
//get div which has a 'name' attribute of 'John'
final HtmlDivision div = (HtmlDivision) htmlPage .getByXPath("//div[@name='John']").get(0);
css 选择器:(我更喜欢它)
final DomNodeList divs = htmlPage .querySelectorAll("div");
for (DomNode div : divs) {
....
}
//get div which has the id 'breadcrumbs'
final DomNode div = htmlPage .querySelector("div#breadcrumbs");
css给出了一个集合查询querySelectorAll和一个单一查询querySelector,如果你没有基础,我给你下面的例子来理解:
htmlPage.querySelectorAll("div") 返回 htmlPage 下面的 div 标签集合
htmlPage.querySelector("div:nth-child(1)") 返回htmlPage下面的div的第一个div
htmlPage .querySelector(".submit") 返回htmlPage下的第一个class=submit标签
htmlPage .querySelector("#submit") 返回htmlPage下id=submit的第一个标签
htmlPage.querySelector("div.submit") 返回htmlPage下第一个带有submit类的div标签
htmlPage.querySelector("div[id='submit']") 返回 htmlPage 下面的第一个 div 标签,id 为 submit
上面的枚举方式相信就够了,如果还不够,可以参考css选择器
下面列出了常见的html标签和HtmlUnit类的对应关系
div -> HtmlDivision
div集合 -> DomNodeList
fieldSet -> HtmlFieldSet
form -> HtmlForm
button -> HtmlButton
a -> HtmlAnchor
-> HtmlXxxInput
( -> HtmlTextInput)
table -> HtmlTable
tr -> HtmlTableRow
td -> TableDataCell
节点的属性样式有一个setAttribute()方法,setNodeValue()设置节点值。你的英语突然提高了吗?几乎所有的标签都能找到对应的类。来看看我的实战:这是一个在线填写温度的excel文档。如果你访问并更改地址,他会提示登录页面上有一个登录按钮。登录按钮,我们现在模拟打开自动登录框:
//这段代码是为了让网页的的某个按钮加载出来之后再执行下面的代码
while (htmlPage.querySelector("#header-login-btn")==null) {
synchronized (htmlPage) {
htmlPage.wait(1000);
}
}
HtmlButton login = htmlPage.querySelector("#header-login-btn");//获取到登陆按钮
if (login!=null){//如果网页上没这个按钮你还要去获取他只会得到一个空对象,所以我们用空的方式可以判断网页上是否有这个按钮
System.out.println("-----未登录测试-----");
htmlPage=login.click();//模拟按钮点击后要将网页返回回来方便动态更新数据
System.out.println(htmlPage.asText());
HtmlAnchor switcher_plogin = htmlPage.querySelector("a[id='switcher_plogin']");
if (switcher_plogin!=null) {//帐号密码登录
System.out.println("-----点击了帐号密码登陆-----");
htmlPage = switcher_plogin.click();
System.out.println(htmlPage.asText());
}
}
System.out.println(htmlPage.asText());
webClient.close();
爬虫最重要的一步就是先调试网页,有哪些按钮,点击哪些,设置哪些值。毕竟,我们要用代码来调度代码。
**扩展:**如果要从网页中获取数据或下载文件,仅依靠HtmlUnit解析是不够的。推荐使用Jsoup库,可以和HtmlUnit一起使用,比较好用,这里就不一一列举了。
三、实现一个小demo
注意:不是所有htmlunit引用的jar包都会报奇怪的错误
使用maven方法更方便
参考: 查看全部
htmlunit抓取动态网页(1.HtmlUnit中文文档获取页面中特定的元素tips:1.)
1.HtmlUnit 简介
HtmlUnit 是一个 java 无界面浏览器库。它模拟 HTML 文档并提供相应的 API,允许您调用页面、填写表单、单击链接等,就像您在“普通”浏览器中所做的那样。它具有相当不错的 JavaScript 支持(仍在改进),甚至能够处理相当复杂的 AJAX 库,根据使用的配置模拟 Chrome、Firefox 或 Internet Explorer。它通常用于测试目的或从 网站 检索信息。
HtmlUnit 不是一个通用的单元测试框架。它是一种模拟浏览器以进行测试的方法,旨在用于其他测试框架,例如 JUnit 或 TestNG。有关介绍,请参见文档“HtmlUnit 入门”。HtmlUnit 用作不同的开源工具,如 Canoo WebTest、JWebUnit、WebDriver、JSFUnit、WETATOR、Celerity、Spring MVC Test HtmlUnit 作为底层“浏览器”。
HtmlUnit 最初由 Gargoyle Software 的 Mike Bowler 编写,并在 Apache 2 许可下发布。从那时起,它收到了许多其他开发者的贡献,今天将得到他们的帮助。
几年前,我在为购物网站 做数据采集工作时偶然发现了HtmlUnit。记得当时页面上的价格数据是抓不到的,httpfox也无法追踪到价格数据的url。就在我手足无措的时候,HtmlUnit出现了,帮我解决了问题。所以今天我要说声谢谢并向大家推荐HtmlUnit。
2.htmlUnit 中文文档
3.1 获取页面的TITLE、XML代码、文本

import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//创建一个webclient
WebClient webClient = new WebClient();
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
//获取页面
HtmlPage page = webClient.getPage("http://www.baidu.com/");
//获取页面的TITLE
str = page.getTitleText();
System.out.println(str);
//获取页面的XML代码
str = page.asXml();
System.out.println(str);
//获取页面的文本
str = page.asText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}

3.2 用不同版本的浏览器打开

import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.html.HtmlDivision;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlBody;
import java.util.List;
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
String str;
//使用FireFox读取网页
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = webClient.getPage("http://www.baidu.com/");
str = page.getTitleText();
System.out.println(str);
//关闭webclient
webClient.closeAllWindows();
}
}

3.3 在页面中查找特定元素
public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//通过id获得"百度一下"按钮
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
System.out.println(btn.getDefaultValue());
//关闭webclient
webClient.closeAllWindows();
}
}
提示:有些元素没有 id 和 name 或其他节点。您可以通过查找其子节点和父节点之间的规律性来获取该元素。具体方法请参考:
它的核心代码是:
final HtmlPage nextPage = ((DomElement)(htmlpage.getElementByName("key").getParentNode().getParentNode())).getLastElementChild().click();
3.4 元素检索

public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//查找所有div
List hbList = page.getByXPath("//div");
HtmlDivision hb = (HtmlDivision)hbList.get(0);
System.out.println(hb.toString());
//查找并获取特定input
List inputList = page.getByXPath("//input[@id='su']");
HtmlInput input = (HtmlInput)inputList.get(0);
System.out.println(input.toString());
//关闭webclient
webClient.closeAllWindows();
}
}

3.5 提交搜索

public class helloHtmlUnit{
public static void main(String[] args) throws Exception{
//创建webclient
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
HtmlPage page = (HtmlPage)webClient.getPage("http://www.baidu.com/");
//获取搜索输入框并提交搜索内容
HtmlInput input = (HtmlInput)page.getHtmlElementById("kw");
System.out.println(input.toString());
input.setValueAttribute("ymd");
System.out.println(input.toString());
//获取搜索按钮并点击
HtmlInput btn = (HtmlInput)page.getHtmlElementById("su");
HtmlPage page2 = btn.click();
//输出新页面的文本
System.out.println(page2.asText());
}
}

3.htmlUnit方法介绍
一、环境介绍
因为我是在自己的spring boot项目中引入的,所以只需要在pom文件中添加依赖即可
net.sourceforge.htmlunit
htmlunit
2.41.0
如果只是爬一点js 网站 建议改一下下面的依赖
net.sourceforge.htmlunit
htmlunit
2.23
两者的区别将在后面讨论。当然,如果你用的不是maven项目(没有pom),可以去官网下载源码库
二、使用
HtmlUnit 使用起来非常简单。使用的时候可以去官网手册查看语法。其实说明书只是介绍,下面听我说就够了;
1、创建客户端并配置客户端
final String url ="https:****";//大家这可以填自己爬虫的地址
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_68);//创建火狐浏览器 2.23版本是FIREFOX_45 new不写参数是默认浏览器
webClient.getOptions().setCssEnabled(false);//(屏蔽)css 因为css并不影响我们抓取数据 反而影响网页渲染效率
webClient.getOptions().setThrowExceptionOnScriptError(false);//(屏蔽)异常
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//(屏蔽)日志
webClient.getOptions().setJavaScriptEnabled(true);//加载js脚本
webClient.getOptions().setTimeout(50000);//设置超时时间
webClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置ajax
HtmlPage htmlPage = webClient.getPage(url);//将客户端获取的树形结构转化为HtmlPage
Thread.sleep(10000);//主线程休眠10秒 让客户端有时间执行js代码 也可以写成webClient.waitForBackgroundJavaScript(1000)
有一个等待js执行,2.41.0非常兼容很多js,但是2.3总是有问题不能刷新网页,2. 41.0 打印也很详细,执行过程比较慢,可能是慢而细致。
远程地址页差不多就到这里了。我们现在要做的就是解析dom节点并填写数据来模拟点击等事件。如果要打印出来 htmlPage.asText() 输出 htmlPage 节点的文本 htmlPage.asXml() 输出 htmlPage 节点的 xml 代码
2、节点获取
在这个链接中,建议准备一点前端知识
HtmlUnit 提供了两种获取节点的方法
XPath 查询:
更详细的xpath解释:
final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
//get list of all divs
final List divs = htmlPage .getByXPath("//div");
//get div which has a 'name' attribute of 'John'
final HtmlDivision div = (HtmlDivision) htmlPage .getByXPath("//div[@name='John']").get(0);
css 选择器:(我更喜欢它)
final DomNodeList divs = htmlPage .querySelectorAll("div");
for (DomNode div : divs) {
....
}
//get div which has the id 'breadcrumbs'
final DomNode div = htmlPage .querySelector("div#breadcrumbs");
css给出了一个集合查询querySelectorAll和一个单一查询querySelector,如果你没有基础,我给你下面的例子来理解:
htmlPage.querySelectorAll("div") 返回 htmlPage 下面的 div 标签集合
htmlPage.querySelector("div:nth-child(1)") 返回htmlPage下面的div的第一个div
htmlPage .querySelector(".submit") 返回htmlPage下的第一个class=submit标签
htmlPage .querySelector("#submit") 返回htmlPage下id=submit的第一个标签
htmlPage.querySelector("div.submit") 返回htmlPage下第一个带有submit类的div标签
htmlPage.querySelector("div[id='submit']") 返回 htmlPage 下面的第一个 div 标签,id 为 submit
上面的枚举方式相信就够了,如果还不够,可以参考css选择器
下面列出了常见的html标签和HtmlUnit类的对应关系
div -> HtmlDivision
div集合 -> DomNodeList
fieldSet -> HtmlFieldSet
form -> HtmlForm
button -> HtmlButton
a -> HtmlAnchor
-> HtmlXxxInput
( -> HtmlTextInput)
table -> HtmlTable
tr -> HtmlTableRow
td -> TableDataCell
节点的属性样式有一个setAttribute()方法,setNodeValue()设置节点值。你的英语突然提高了吗?几乎所有的标签都能找到对应的类。来看看我的实战:这是一个在线填写温度的excel文档。如果你访问并更改地址,他会提示登录页面上有一个登录按钮。登录按钮,我们现在模拟打开自动登录框:
//这段代码是为了让网页的的某个按钮加载出来之后再执行下面的代码
while (htmlPage.querySelector("#header-login-btn")==null) {
synchronized (htmlPage) {
htmlPage.wait(1000);
}
}
HtmlButton login = htmlPage.querySelector("#header-login-btn");//获取到登陆按钮
if (login!=null){//如果网页上没这个按钮你还要去获取他只会得到一个空对象,所以我们用空的方式可以判断网页上是否有这个按钮
System.out.println("-----未登录测试-----");
htmlPage=login.click();//模拟按钮点击后要将网页返回回来方便动态更新数据
System.out.println(htmlPage.asText());
HtmlAnchor switcher_plogin = htmlPage.querySelector("a[id='switcher_plogin']");
if (switcher_plogin!=null) {//帐号密码登录
System.out.println("-----点击了帐号密码登陆-----");
htmlPage = switcher_plogin.click();
System.out.println(htmlPage.asText());
}
}
System.out.println(htmlPage.asText());
webClient.close();
爬虫最重要的一步就是先调试网页,有哪些按钮,点击哪些,设置哪些值。毕竟,我们要用代码来调度代码。
**扩展:**如果要从网页中获取数据或下载文件,仅依靠HtmlUnit解析是不够的。推荐使用Jsoup库,可以和HtmlUnit一起使用,比较好用,这里就不一一列举了。
三、实现一个小demo
注意:不是所有htmlunit引用的jar包都会报奇怪的错误
使用maven方法更方便
参考:
htmlunit抓取动态网页(基于Webmagic的动态网页爬虫系统-DynCrawler.系统)
网站优化 • 优采云 发表了文章 • 0 个评论 • 69 次浏览 • 2022-01-29 17:16
概括:
随着网页数量的爆炸式增长,传统的中心化爬虫难以满足实际应用。此外,Ajax 技术在 Web 应用中的广泛普及,给传统的 Web 开发带来了新的革命。为了提高用户体验,用户可以与远程服务器进行良好的交互。典型应用包括校园BBS、博客网站等,这些大量动态网页的出现给传统的网络爬虫带来了巨大的挑战。障碍。它影响爬虫的效率,也影响网页内容的获取。针对以上两个问题,本文设计了一种基于WebMagic爬虫框架的分布式动态网络爬虫系统Dis-Dyn Crawler。系统采用SOA架构为了提高解析效率,系统将HtmlUnit所需的JavaScript等文件缓存在Redis数据库中,并进行页面渲染。无需每次都从网络下载,减少网络请求,提高解析效率;异步页面下载器的实现进一步提高了系统的整体效率。本文从功能和性能两个方面对Dis-Dyn爬虫系统进行了分析。.通过与现有分布式网络爬虫工具的爬取能力对比,验证了基于Webmagic的动态网络爬虫是高效的。通过与现有动态网页解析工具的对比,验证了本文提出的Dis-Dyn爬虫系统是高效的。效率和可行性。
展开 查看全部
htmlunit抓取动态网页(基于Webmagic的动态网页爬虫系统-DynCrawler.系统)
概括:
随着网页数量的爆炸式增长,传统的中心化爬虫难以满足实际应用。此外,Ajax 技术在 Web 应用中的广泛普及,给传统的 Web 开发带来了新的革命。为了提高用户体验,用户可以与远程服务器进行良好的交互。典型应用包括校园BBS、博客网站等,这些大量动态网页的出现给传统的网络爬虫带来了巨大的挑战。障碍。它影响爬虫的效率,也影响网页内容的获取。针对以上两个问题,本文设计了一种基于WebMagic爬虫框架的分布式动态网络爬虫系统Dis-Dyn Crawler。系统采用SOA架构为了提高解析效率,系统将HtmlUnit所需的JavaScript等文件缓存在Redis数据库中,并进行页面渲染。无需每次都从网络下载,减少网络请求,提高解析效率;异步页面下载器的实现进一步提高了系统的整体效率。本文从功能和性能两个方面对Dis-Dyn爬虫系统进行了分析。.通过与现有分布式网络爬虫工具的爬取能力对比,验证了基于Webmagic的动态网络爬虫是高效的。通过与现有动态网页解析工具的对比,验证了本文提出的Dis-Dyn爬虫系统是高效的。效率和可行性。
展开
htmlunit抓取动态网页(没写代码实现获取网页源代码代码模拟按钮的方法)
网站优化 • 优采云 发表了文章 • 0 个评论 • 67 次浏览 • 2022-01-29 11:01
1.几行代码即可获取网页源代码。
final WebClient webClient=new WebClient();
final HtmlPage page=webClient.getPage("http://www.baidu.com");
System.out.println(page.asText()); //asText()是以文本格式显示
System.out.println(page.asXml()); //asXml()是以xml格式显示
webClient.closeAllWindows();
2.模拟文本框和模拟按钮提交,我们来模拟模拟百度搜索关键字的实现。
// 得到浏览器对象,直接New一个就能得到,现在就好比说你得到了一个浏览器了
WebClient webclient = new WebClient();
// 这里是配置一下不加载css和javaScript,因为httpunit对javascript兼容性不太好
webclient.getOptions().setCssEnabled(false);
webclient.getOptions().setJavaScriptEnabled(false);
// 做的第一件事,去拿到这个网页,只需要调用getPage这个方法即可
HtmlPage htmlpage = webclient.getPage("http://baidu.com");
// 根据名字得到一个表单,查看上面这个网页的源代码可以发现表单的名字叫“f”
final HtmlForm form = htmlpage.getFormByName("f");
// 同样道理,获取”百度一下“这个按钮
final HtmlSubmitInput button = form.getInputByValue("百度一下");
// 得到搜索框
final HtmlTextInput textField = form.getInputByName("q1");
//搜索我的id
textField.setValueAttribute("th是个小屁孩");
// 输入好了,我们点一下这个按钮
final HtmlPage nextPage = button.click();
// 我把结果转成String
String result = nextPage.asXml();
System.out.println(result); //得到的是点击后的网页
感觉httpunit比httpclient简单多了。 Java爬虫以后可以多尝试这个框架。提取节点的方法有很多,可以直接调用,但是好像不能从div的类中提取节点,但是可以根据id抓取。获取节点,唉,如果 div 没有写入 id,我不知道如何获取 网站。好像没有这样的方法可以按类来抓取。懂的同学可以给点思路。 查看全部
htmlunit抓取动态网页(没写代码实现获取网页源代码代码模拟按钮的方法)
1.几行代码即可获取网页源代码。
final WebClient webClient=new WebClient();
final HtmlPage page=webClient.getPage("http://www.baidu.com");
System.out.println(page.asText()); //asText()是以文本格式显示
System.out.println(page.asXml()); //asXml()是以xml格式显示
webClient.closeAllWindows();
2.模拟文本框和模拟按钮提交,我们来模拟模拟百度搜索关键字的实现。
// 得到浏览器对象,直接New一个就能得到,现在就好比说你得到了一个浏览器了
WebClient webclient = new WebClient();
// 这里是配置一下不加载css和javaScript,因为httpunit对javascript兼容性不太好
webclient.getOptions().setCssEnabled(false);
webclient.getOptions().setJavaScriptEnabled(false);
// 做的第一件事,去拿到这个网页,只需要调用getPage这个方法即可
HtmlPage htmlpage = webclient.getPage("http://baidu.com");
// 根据名字得到一个表单,查看上面这个网页的源代码可以发现表单的名字叫“f”
final HtmlForm form = htmlpage.getFormByName("f");
// 同样道理,获取”百度一下“这个按钮
final HtmlSubmitInput button = form.getInputByValue("百度一下");
// 得到搜索框
final HtmlTextInput textField = form.getInputByName("q1");
//搜索我的id
textField.setValueAttribute("th是个小屁孩");
// 输入好了,我们点一下这个按钮
final HtmlPage nextPage = button.click();
// 我把结果转成String
String result = nextPage.asXml();
System.out.println(result); //得到的是点击后的网页
感觉httpunit比httpclient简单多了。 Java爬虫以后可以多尝试这个框架。提取节点的方法有很多,可以直接调用,但是好像不能从div的类中提取节点,但是可以根据id抓取。获取节点,唉,如果 div 没有写入 id,我不知道如何获取 网站。好像没有这样的方法可以按类来抓取。懂的同学可以给点思路。
htmlunit抓取动态网页(一个百度动态页面SEO优化动态网页的办法和内容有哪些)
网站优化 • 优采云 发表了文章 • 0 个评论 • 56 次浏览 • 2022-01-25 11:03
企业要想做好网站网络推广,就需要了解搜索引擎的爬取规则,做好百度动态页面SEO。相信大家都知道搜索引擎抓取动态页面的难度。让成长超人的小编来给我们讲解一下如何优化动态页面。
1. 设置静态导入
在“动静结合、静制动”的原则指导下,可以对网站进行一些修正,尽可能提高动态网页在搜索引擎中的可见度。网络实现方法,例如将动态网页编译成静态主页或站点地图的链接,在静态目录中显示动态页面。也许为动态页面创建一个特殊的静态导入页面,链接到动态页面,并将静态导入页面提交给搜索引擎。
2. 付费登录搜索引擎
对于动态的网站,它由内容管理系统发布并连接到整个网站 数据库。在线推广的直接方式是登录并付费。提倡将动态网页直接提交到搜索引擎目录或者做关键词广告,保证网站被搜索。
3.改进的搜索引擎支持
搜索引擎一直在改进对动态页面的支持,但是这些搜索引擎在抓取动态页面时,为了防止搜索机器人的陷阱,搜索引擎只抓取动态页面和链接到静态页面的动态页面链接。不再抓取动态页面,这意味着不会对动态页面中的链接进行深入访问。
相信我们对成长超人为我们编写的SEO优化动态页面的方法和内容有一定的了解。事实上,修订并不适合所有人。您可以获得更多 SEO 优化的内容。看看这个网站上的其他网络推广技巧和经验,相信你会收获不少。 查看全部
htmlunit抓取动态网页(一个百度动态页面SEO优化动态网页的办法和内容有哪些)
企业要想做好网站网络推广,就需要了解搜索引擎的爬取规则,做好百度动态页面SEO。相信大家都知道搜索引擎抓取动态页面的难度。让成长超人的小编来给我们讲解一下如何优化动态页面。
1. 设置静态导入
在“动静结合、静制动”的原则指导下,可以对网站进行一些修正,尽可能提高动态网页在搜索引擎中的可见度。网络实现方法,例如将动态网页编译成静态主页或站点地图的链接,在静态目录中显示动态页面。也许为动态页面创建一个特殊的静态导入页面,链接到动态页面,并将静态导入页面提交给搜索引擎。
2. 付费登录搜索引擎
对于动态的网站,它由内容管理系统发布并连接到整个网站 数据库。在线推广的直接方式是登录并付费。提倡将动态网页直接提交到搜索引擎目录或者做关键词广告,保证网站被搜索。
3.改进的搜索引擎支持
搜索引擎一直在改进对动态页面的支持,但是这些搜索引擎在抓取动态页面时,为了防止搜索机器人的陷阱,搜索引擎只抓取动态页面和链接到静态页面的动态页面链接。不再抓取动态页面,这意味着不会对动态页面中的链接进行深入访问。
相信我们对成长超人为我们编写的SEO优化动态页面的方法和内容有一定的了解。事实上,修订并不适合所有人。您可以获得更多 SEO 优化的内容。看看这个网站上的其他网络推广技巧和经验,相信你会收获不少。
htmlunit抓取动态网页(PythonJavaScript:如何利用Webkit从从渲染网页中获取数据)
网站优化 • 优采云 发表了文章 • 0 个评论 • 45 次浏览 • 2022-01-25 10:19
原来的
主题 Python JavaScript
当我们进行网络爬取时,我们会使用一定的规则从返回的 HTML 数据中提取有效信息。但是如果网页收录 JavaScript 代码,我们必须渲染它以获取原创数据。在这一点上,如果我们仍然以通常的方式从中抓取数据,我们将一无所获。浏览器知道如何处理这段代码并显示出来,但是我们的程序应该如何处理这段代码呢?接下来,我将介绍一种简单粗暴的方法来抓取收录 JavaScript 代码的网页信息。
大多数人使用 lxml 和 BeautifulSoup 这两个包来提取数据。在这篇文章中我不会涉及任何爬虫框架的内容,因为我只使用了最基本的 lxml 包来处理数据。你可能想知道为什么我更喜欢 lxml。那是因为lxml使用元素遍历来处理数据,而不是像BeautifulSoup那样使用正则表达式来提取数据。在这篇文章中我要介绍一个非常有趣的案例——突然发现我的文章出现在最近的Pycoders周刊第147期,所以我想爬取Pycoders周刊中所有档案的链接。
显然,这是一个带有 JavaScript 渲染的网页。我想抓取网页中的所有个人资料信息和相应的链接信息。那么我该怎么办呢?首先,我们无法通过 HTTP 方法获取任何信息。
1import requests
2from lxml import html
3
4# storing response
5response = requests.get('http://pycoders.com/archive')
6# creating lxml tree from response body
7tree = html.fromstring(response.text)
8
9# Finding all anchor tags in response
10print tree.xpath('//div[@class="campaign"]/a/@href')
11
12
当我们运行上述代码时,我们无法获得任何信息。这怎么可能?网页清楚地显示了这么多文件的信息。接下来我们需要考虑如何解决这个问题?
如何获取内容信息?
接下来我将展示如何使用 Web 工具包从 JS 渲染的网页中获取数据。什么是网络套件?Web 工具包可以做任何浏览器可以处理的事情。对于某些浏览器,Web kit 是底层的网页渲染工具。Web kit 是 QT 库的一部分,所以如果你已经安装了 QT 和 PyQT4 库,你可以直接运行它。
您可以使用命令行安装存储库:
1sudo apt-get install python-qt4
2
3
现在所有的准备工作都完成了,我们将使用一种全新的方法来提取信息。
解决方案
我们首先通过 Web kit 发送请求信息,然后等待页面完全加载,然后将其分配给变量。接下来我们使用 lxml 从 HTML 数据中提取有效信息。这个过程需要一点时间,但您会惊讶地看到整个页面加载完毕。
1import sys
2from PyQt4.QtGui import *
3from PyQt4.Qtcore import *
4from PyQt4.QtWebKit import *
5
6class Render(QWebPage):
7 def __init__(self, url):
8 self.app = QApplication(sys.argv)
9 QWebPage.__init__(self)
10 self.loadFinished.connect(self._loadFinished)
11 self.mainFrame().load(QUrl(url))
12 self.app.exec_()
13
14 def _loadFinished(self, result):
15 self.frame = self.mainFrame()
16 self.app.quit()
17
18
Render 类可用于渲染网页。当我们创建一个新的 Render 类时,它可以加载 url 中的所有信息并将其存储在一个新的框架中。
使用上面的代码,我们将 HTML 结果存储在变量 result 中。由于lxml不能直接处理这种特殊的字符串数据,我们需要转换数据格式。
1# QString should be converted to string before processed by lxml
2formatted_result = str(result.toAscii())
3
4# Next build lxml tree from formatted_result
5tree = html.fromstring(formatted_result)
6
7# Now using correct Xpath we are fetching URL of archives
8archive_links = tree.xpath('//div[@class="campaign"]/a/@href')
9print archive_links
10
11
使用上面的代码,我们可以得到所有的文件链接信息,然后我们可以使用这些Render和这些URL链接来提取文本内容信息。Web kit 提供了一个强大的网页渲染工具,我们可以使用这个工具从 JS 渲染的网页中抓取有效的信息。
在本文中,我介绍了一种从 JS 渲染的网页中获取信息的有效方法。虽然这个工具比较慢,但是非常简单粗暴。我希望你会喜欢这个文章。现在您可以将此方法应用于您发现难以处理的任何网页。
愿你事事如意。
原文链接: 查看全部
htmlunit抓取动态网页(PythonJavaScript:如何利用Webkit从从渲染网页中获取数据)
原来的
主题 Python JavaScript
当我们进行网络爬取时,我们会使用一定的规则从返回的 HTML 数据中提取有效信息。但是如果网页收录 JavaScript 代码,我们必须渲染它以获取原创数据。在这一点上,如果我们仍然以通常的方式从中抓取数据,我们将一无所获。浏览器知道如何处理这段代码并显示出来,但是我们的程序应该如何处理这段代码呢?接下来,我将介绍一种简单粗暴的方法来抓取收录 JavaScript 代码的网页信息。
大多数人使用 lxml 和 BeautifulSoup 这两个包来提取数据。在这篇文章中我不会涉及任何爬虫框架的内容,因为我只使用了最基本的 lxml 包来处理数据。你可能想知道为什么我更喜欢 lxml。那是因为lxml使用元素遍历来处理数据,而不是像BeautifulSoup那样使用正则表达式来提取数据。在这篇文章中我要介绍一个非常有趣的案例——突然发现我的文章出现在最近的Pycoders周刊第147期,所以我想爬取Pycoders周刊中所有档案的链接。
显然,这是一个带有 JavaScript 渲染的网页。我想抓取网页中的所有个人资料信息和相应的链接信息。那么我该怎么办呢?首先,我们无法通过 HTTP 方法获取任何信息。
1import requests
2from lxml import html
3
4# storing response
5response = requests.get('http://pycoders.com/archive')
6# creating lxml tree from response body
7tree = html.fromstring(response.text)
8
9# Finding all anchor tags in response
10print tree.xpath('//div[@class="campaign"]/a/@href')
11
12
当我们运行上述代码时,我们无法获得任何信息。这怎么可能?网页清楚地显示了这么多文件的信息。接下来我们需要考虑如何解决这个问题?
如何获取内容信息?
接下来我将展示如何使用 Web 工具包从 JS 渲染的网页中获取数据。什么是网络套件?Web 工具包可以做任何浏览器可以处理的事情。对于某些浏览器,Web kit 是底层的网页渲染工具。Web kit 是 QT 库的一部分,所以如果你已经安装了 QT 和 PyQT4 库,你可以直接运行它。
您可以使用命令行安装存储库:
1sudo apt-get install python-qt4
2
3
现在所有的准备工作都完成了,我们将使用一种全新的方法来提取信息。
解决方案
我们首先通过 Web kit 发送请求信息,然后等待页面完全加载,然后将其分配给变量。接下来我们使用 lxml 从 HTML 数据中提取有效信息。这个过程需要一点时间,但您会惊讶地看到整个页面加载完毕。
1import sys
2from PyQt4.QtGui import *
3from PyQt4.Qtcore import *
4from PyQt4.QtWebKit import *
5
6class Render(QWebPage):
7 def __init__(self, url):
8 self.app = QApplication(sys.argv)
9 QWebPage.__init__(self)
10 self.loadFinished.connect(self._loadFinished)
11 self.mainFrame().load(QUrl(url))
12 self.app.exec_()
13
14 def _loadFinished(self, result):
15 self.frame = self.mainFrame()
16 self.app.quit()
17
18
Render 类可用于渲染网页。当我们创建一个新的 Render 类时,它可以加载 url 中的所有信息并将其存储在一个新的框架中。
使用上面的代码,我们将 HTML 结果存储在变量 result 中。由于lxml不能直接处理这种特殊的字符串数据,我们需要转换数据格式。
1# QString should be converted to string before processed by lxml
2formatted_result = str(result.toAscii())
3
4# Next build lxml tree from formatted_result
5tree = html.fromstring(formatted_result)
6
7# Now using correct Xpath we are fetching URL of archives
8archive_links = tree.xpath('//div[@class="campaign"]/a/@href')
9print archive_links
10
11
使用上面的代码,我们可以得到所有的文件链接信息,然后我们可以使用这些Render和这些URL链接来提取文本内容信息。Web kit 提供了一个强大的网页渲染工具,我们可以使用这个工具从 JS 渲染的网页中抓取有效的信息。
在本文中,我介绍了一种从 JS 渲染的网页中获取信息的有效方法。虽然这个工具比较慢,但是非常简单粗暴。我希望你会喜欢这个文章。现在您可以将此方法应用于您发现难以处理的任何网页。
愿你事事如意。
原文链接:
htmlunit抓取动态网页(就是怎么用htmlunit爬虫工具来爬取京东页面下该类目下)
网站优化 • 优采云 发表了文章 • 0 个评论 • 46 次浏览 • 2022-01-24 18:07
由于是第一次使用爬虫爬取网页内容,对于一些特殊情况我不是很擅长处理。在这里,我将与您分享我遇到的一些情况。
public static String getPage(String s_url, String charset) {
if (s_url == null) {
return null;
}
try {
URL url = new URL(s_url);
BufferedReader bReader = new BufferedReader(new InputStreamReader(url.openStream(), charset));
String s;
StringBuffer sBuffer = new StringBuffer();
while ((s=bReader.readLine())!=null) {
sBuffer = sBuffer.append(s);
}
url = null;
return sBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
上面的代码应该是最简单的获取网页源代码的方法了。您可以通过网页的url和编码方式直接获取网页的源代码,从而获得您想要的信息。但事情并不总是像想象的那么简单。目前的情况是这样的。我需要爬取的页面是京东三级分类下的商品信息。这种编码的结果都是乱码。后来在访问地址后面加上了?enc=utf-8,得到的页面终于没有乱码了,但是京东页面返回的结果却是“No product found”,真是心碎。如果大神知道如何解决这个问题,请告诉我。
好了,废话就说到这里,下面是如何使用htmlunit爬虫工具爬取京东页面
System.out.println("开始爬取页面了...");
//创建一个webclient
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setTimeout(10000);
try{
//获取页面
HtmlPage page = webClient.getPage("http://list.jd.com/list.html?cat=1620,1621,1627");
List divs = page.getByXPath("//div[@id='plist']");
HtmlDivision div = (HtmlDivision)divs.get(0);
HtmlUnorderedList ul = (HtmlUnorderedList)div.getFirstChild();
List lis = ul.getHtmlElementsByTagName("li");
for(int i = 0; i < lis.size(); i ++){
HtmlListItem li = lis.get(i);
String index = li.getAttribute("index");
if(index == null || "".equals(index))
continue;
//打印出页面中的商品所对应的skuid
System.out.println("第" + li.getAttribute("index") + "个商品的skuid=" + li.getAttribute("data-sku"));
}
//获取该类目下的商品总页数
List divs2 = page.getByXPath("//div[@id='J_bottomPage']");
HtmlDivision div2 = (HtmlDivision)divs2.get(0);
List b = div2.getHtmlElementsByTagName("b");
for(int i = 0; i < b.size(); i++){
String classname = b.get(i).getAttribute("class");
if(classname != null && !"".equals(classname)){
continue;
}
String pagetotal = b.get(i).getFirstChild().toString();
System.out.println("总页数为" + pagetotal);
}
System.out.println("哈哈");
}catch(Exception e){
e.printStackTrace();
}finally{
//关闭webclient
webClient.closeAllWindows();
}
如上,可以得到京东页面上该分类下所有产品的skuid和总页数。下一个问题很好解决~
htmlunit相关jar包下载地址: 查看全部
htmlunit抓取动态网页(就是怎么用htmlunit爬虫工具来爬取京东页面下该类目下)
由于是第一次使用爬虫爬取网页内容,对于一些特殊情况我不是很擅长处理。在这里,我将与您分享我遇到的一些情况。
public static String getPage(String s_url, String charset) {
if (s_url == null) {
return null;
}
try {
URL url = new URL(s_url);
BufferedReader bReader = new BufferedReader(new InputStreamReader(url.openStream(), charset));
String s;
StringBuffer sBuffer = new StringBuffer();
while ((s=bReader.readLine())!=null) {
sBuffer = sBuffer.append(s);
}
url = null;
return sBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
上面的代码应该是最简单的获取网页源代码的方法了。您可以通过网页的url和编码方式直接获取网页的源代码,从而获得您想要的信息。但事情并不总是像想象的那么简单。目前的情况是这样的。我需要爬取的页面是京东三级分类下的商品信息。这种编码的结果都是乱码。后来在访问地址后面加上了?enc=utf-8,得到的页面终于没有乱码了,但是京东页面返回的结果却是“No product found”,真是心碎。如果大神知道如何解决这个问题,请告诉我。
好了,废话就说到这里,下面是如何使用htmlunit爬虫工具爬取京东页面
System.out.println("开始爬取页面了...");
//创建一个webclient
WebClient webClient = new WebClient(BrowserVersion.FIREFOX_24);
//htmlunit 对css和javascript的支持不好,所以请关闭之
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setTimeout(10000);
try{
//获取页面
HtmlPage page = webClient.getPage("http://list.jd.com/list.html?cat=1620,1621,1627");
List divs = page.getByXPath("//div[@id='plist']");
HtmlDivision div = (HtmlDivision)divs.get(0);
HtmlUnorderedList ul = (HtmlUnorderedList)div.getFirstChild();
List lis = ul.getHtmlElementsByTagName("li");
for(int i = 0; i < lis.size(); i ++){
HtmlListItem li = lis.get(i);
String index = li.getAttribute("index");
if(index == null || "".equals(index))
continue;
//打印出页面中的商品所对应的skuid
System.out.println("第" + li.getAttribute("index") + "个商品的skuid=" + li.getAttribute("data-sku"));
}
//获取该类目下的商品总页数
List divs2 = page.getByXPath("//div[@id='J_bottomPage']");
HtmlDivision div2 = (HtmlDivision)divs2.get(0);
List b = div2.getHtmlElementsByTagName("b");
for(int i = 0; i < b.size(); i++){
String classname = b.get(i).getAttribute("class");
if(classname != null && !"".equals(classname)){
continue;
}
String pagetotal = b.get(i).getFirstChild().toString();
System.out.println("总页数为" + pagetotal);
}
System.out.println("哈哈");
}catch(Exception e){
e.printStackTrace();
}finally{
//关闭webclient
webClient.closeAllWindows();
}
如上,可以得到京东页面上该分类下所有产品的skuid和总页数。下一个问题很好解决~
htmlunit相关jar包下载地址:
htmlunit抓取动态网页(1.HtmlUnit的学习方法是什么?怎么样?HtmlUnit)
网站优化 • 优采云 发表了文章 • 0 个评论 • 52 次浏览 • 2022-01-23 05:07
1.HtmlUnit 是一个用java 编写的无界面浏览器,它可以模拟html 文档、通过API 调用页面、填写表单、点击链接等等。像普通浏览器一样运行。通常用于测试和从网页中抓取信息。而HtmlUnit有HttpClient和soup的功能,但是速度比较慢,但是如果取消它解析css和js的功能,速度也会有所提升,默认开启。
2.这里,HtmlUnit是用来爬取数据的,主要是为了获取他的js和css。
3.主要代码如下
package com.los;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.los.util.DownlandPic;
import java.io.IOException;
import java.util.regex.Pattern;
public class HtmlUnitTest {
public static void main(String[] args) throws IOException {
DownlandPic dd = new DownlandPic();
WebClient webClient = new WebClient();//实例化web客户端
//http://www.bdqn.cn/ https://www.baidu.com/?tn=78000241_22_hao_pg
String url = "http://www.bdqn.cn/";
HtmlPage page = webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000); //等侍js脚本执行完成
System.out.println(page.asXml());
DomNodeList img = page.getElementsByTagName("script");
for (int i=0;i 0) {
output.write(buffer, 0, length);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static int getCharacterPosition3(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 2){
break;
}
}
return slashMatcher.start();
}
public static int getCharacterPosition4(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 3){
break;
}
}
return slashMatcher.start();
}
public static void main(String[] args) {
String content = "<img class=\"lazy\" data-original=\"/img/newImg/news_img2.jpg\" src=\"/img/newImg/news2.jpg\" style=\"display: block;\"/>";
System.out.println(getCharacterPosition3(content));
System.out.println(getCharacterPosition4(content));
String substring = content.substring(getCharacterPosition3(content), getCharacterPosition4(content));
System.out.println(substring);
}
}
3.因为这里网页中的图片地址是相对路径,所以在下载的时候到页面中找到它的绝对路径,拼接在下载地址中。下载的路径必须与图片标签中的地址对应爬取后存储在本地页面,否则无法找到。
3.之所以在匹配“时写2和3是根据这里爬取的数据。
4.相对于其他爬取网页的写法,这个可能更简单,但是更能体现效果。如有错误请多多指教。至于页面不会显示,涉及隐私。
5.了解HtmlUnit请参考:地址 查看全部
htmlunit抓取动态网页(1.HtmlUnit的学习方法是什么?怎么样?HtmlUnit)
1.HtmlUnit 是一个用java 编写的无界面浏览器,它可以模拟html 文档、通过API 调用页面、填写表单、点击链接等等。像普通浏览器一样运行。通常用于测试和从网页中抓取信息。而HtmlUnit有HttpClient和soup的功能,但是速度比较慢,但是如果取消它解析css和js的功能,速度也会有所提升,默认开启。
2.这里,HtmlUnit是用来爬取数据的,主要是为了获取他的js和css。
3.主要代码如下
package com.los;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.los.util.DownlandPic;
import java.io.IOException;
import java.util.regex.Pattern;
public class HtmlUnitTest {
public static void main(String[] args) throws IOException {
DownlandPic dd = new DownlandPic();
WebClient webClient = new WebClient();//实例化web客户端
//http://www.bdqn.cn/ https://www.baidu.com/?tn=78000241_22_hao_pg
String url = "http://www.bdqn.cn/";
HtmlPage page = webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000); //等侍js脚本执行完成
System.out.println(page.asXml());
DomNodeList img = page.getElementsByTagName("script");
for (int i=0;i 0) {
output.write(buffer, 0, length);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static int getCharacterPosition3(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 2){
break;
}
}
return slashMatcher.start();
}
public static int getCharacterPosition4(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 3){
break;
}
}
return slashMatcher.start();
}
public static void main(String[] args) {
String content = "<img class=\"lazy\" data-original=\"/img/newImg/news_img2.jpg\" src=\"/img/newImg/news2.jpg\" style=\"display: block;\"/>";
System.out.println(getCharacterPosition3(content));
System.out.println(getCharacterPosition4(content));
String substring = content.substring(getCharacterPosition3(content), getCharacterPosition4(content));
System.out.println(substring);
}
}
3.因为这里网页中的图片地址是相对路径,所以在下载的时候到页面中找到它的绝对路径,拼接在下载地址中。下载的路径必须与图片标签中的地址对应爬取后存储在本地页面,否则无法找到。
3.之所以在匹配“时写2和3是根据这里爬取的数据。

4.相对于其他爬取网页的写法,这个可能更简单,但是更能体现效果。如有错误请多多指教。至于页面不会显示,涉及隐私。
5.了解HtmlUnit请参考:地址
htmlunit抓取动态网页(搜狗微信公众号更新公告(2015.03.23) )
网站优化 • 优采云 发表了文章 • 0 个评论 • 53 次浏览 • 2022-01-23 05:04
)
最后更新于 2018.1.3
只为自己留个记录
要添加的功能:
1.获取历史中的所有消息
2. 爬取10多条数据
3.公众号信息自定义抓取
下面以搜狗微信公众号搜索微信公众号为例!
搜狗微信公众号作为分析入口:[此处填写公众号]&ie=utf8&sug=n&sug_type=
DEMO 中的完整 URL 为:%E6%AF%8F%E6%97%A5%E8%8A%82%E5%A5%8F&ie=utf8&sug=n&sug_type=
package cc.buckler.test;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Test;
import java.io.IOException;
public class TestData {
private String ENTRY_URL = "http://weixin.sogou.com/weixin ... %3B//入口地址
private String QUERY_WORD = "DOTA每日节奏";//查询参数
private String BASE_URL = "";//从入口进入公众号后的公众号地址
private String WE_CHAT_URL = "http://mp.weixin.qq.com";//微信公众号官方入口
private int NEW_MSG_ID = 0;//最新msgId
private int MSG_NUM = 20;//需要获取的数量
@Test
public void getData() {
String url = String.format(ENTRY_URL, QUERY_WORD);
//System.out.println(url);
WebClient webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setRedirectEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setTimeout(50000);
Document doc = null;
try {
//首先用jsoup获取搜狗入口公众号连接
doc = Jsoup.connect(url).get();
//System.out.println("doc:" + doc);
BASE_URL = doc.select("p a").attr("href");
//System.out.println(BASE_URL);
//使用htmlunit加载公众号文章列表
HtmlPage htmlPage = webClient.getPage(BASE_URL);
webClient.waitForBackgroundJavaScript(10000);
doc = Jsoup.parse(htmlPage.asXml());
//System.out.println("doc:" + doc);
//获取最新文章msgid,之后的循环用msgid-1
String lastMsgId = doc.select(".weui_media_box").attr("msgid");
NEW_MSG_ID = Integer.parseInt(lastMsgId);
//System.out.println(NEW_MSG_ID);
for (int i = NEW_MSG_ID; i >= NEW_MSG_ID - MSG_NUM; i--) {
String articalPrev = "#WXAPPMSG";
String articalId = articalPrev + i;
String h4 = articalId + " h4";
String weui_media_desc = articalId + " .weui_media_desc";
String weui_media_extra_info = articalId + " .weui_media_extra_info";
System.out.println(articalId);
String title = doc.select(h4).text();
System.out.println(title);
String detailUrl = doc.select(h4).attr("hrefs");//2018.1.3 ok
System.out.println(WE_CHAT_URL + detailUrl);
String note = doc.select(weui_media_desc).text();//2018.1.3 ok
if (note.compareToIgnoreCase("") == 0) {
continue;
}
System.out.println(note);
String releaseDate = doc.select(weui_media_extra_info).text().toString();//2018.1.3 ok
if (releaseDate.compareToIgnoreCase("") == 0) {
continue;
}
System.out.println(releaseDate);
}
webClient.close();
} catch (IOException e) {
e.printStackTrace();
webClient.close();
}
}
} 查看全部
htmlunit抓取动态网页(搜狗微信公众号更新公告(2015.03.23)
)
最后更新于 2018.1.3
只为自己留个记录
要添加的功能:
1.获取历史中的所有消息
2. 爬取10多条数据
3.公众号信息自定义抓取
下面以搜狗微信公众号搜索微信公众号为例!
搜狗微信公众号作为分析入口:[此处填写公众号]&ie=utf8&sug=n&sug_type=
DEMO 中的完整 URL 为:%E6%AF%8F%E6%97%A5%E8%8A%82%E5%A5%8F&ie=utf8&sug=n&sug_type=
package cc.buckler.test;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Test;
import java.io.IOException;
public class TestData {
private String ENTRY_URL = "http://weixin.sogou.com/weixin ... %3B//入口地址
private String QUERY_WORD = "DOTA每日节奏";//查询参数
private String BASE_URL = "";//从入口进入公众号后的公众号地址
private String WE_CHAT_URL = "http://mp.weixin.qq.com";//微信公众号官方入口
private int NEW_MSG_ID = 0;//最新msgId
private int MSG_NUM = 20;//需要获取的数量
@Test
public void getData() {
String url = String.format(ENTRY_URL, QUERY_WORD);
//System.out.println(url);
WebClient webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setRedirectEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setTimeout(50000);
Document doc = null;
try {
//首先用jsoup获取搜狗入口公众号连接
doc = Jsoup.connect(url).get();
//System.out.println("doc:" + doc);
BASE_URL = doc.select("p a").attr("href");
//System.out.println(BASE_URL);
//使用htmlunit加载公众号文章列表
HtmlPage htmlPage = webClient.getPage(BASE_URL);
webClient.waitForBackgroundJavaScript(10000);
doc = Jsoup.parse(htmlPage.asXml());
//System.out.println("doc:" + doc);
//获取最新文章msgid,之后的循环用msgid-1
String lastMsgId = doc.select(".weui_media_box").attr("msgid");
NEW_MSG_ID = Integer.parseInt(lastMsgId);
//System.out.println(NEW_MSG_ID);
for (int i = NEW_MSG_ID; i >= NEW_MSG_ID - MSG_NUM; i--) {
String articalPrev = "#WXAPPMSG";
String articalId = articalPrev + i;
String h4 = articalId + " h4";
String weui_media_desc = articalId + " .weui_media_desc";
String weui_media_extra_info = articalId + " .weui_media_extra_info";
System.out.println(articalId);
String title = doc.select(h4).text();
System.out.println(title);
String detailUrl = doc.select(h4).attr("hrefs");//2018.1.3 ok
System.out.println(WE_CHAT_URL + detailUrl);
String note = doc.select(weui_media_desc).text();//2018.1.3 ok
if (note.compareToIgnoreCase("") == 0) {
continue;
}
System.out.println(note);
String releaseDate = doc.select(weui_media_extra_info).text().toString();//2018.1.3 ok
if (releaseDate.compareToIgnoreCase("") == 0) {
continue;
}
System.out.println(releaseDate);
}
webClient.close();
} catch (IOException e) {
e.printStackTrace();
webClient.close();
}
}
}
htmlunit抓取动态网页(.xmlmaven依赖代码 )
网站优化 • 优采云 发表了文章 • 0 个评论 • 72 次浏览 • 2022-01-22 17:12
)
今天用jsoup做爬虫的时候发现jsoup只能爬静态页面,对ajax和json动态生成页面的支持不友好。
所以我尝试直接将param和data header随请求一起发送,希望直接返回json数据,但是可能因为网站接口不支持而无法成功。
尝试了其他方法后,从网上发现可以用htmlunit模拟浏览器,生成动态网页,然后用jsoup解析生成的动态网页
以下是pom.xml maven依赖代码
以下是java代码
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.io.IOException;
public class JsoupTest {
public static void main(String[] args) {
queryDocument("北斗");
}
public static void queryDocument(String documentName){
WebClient browser = new WebClient();
browser.getOptions().setCssEnabled(false);
browser.getOptions().setJavaScriptEnabled(true);
browser.getOptions().setThrowExceptionOnScriptError(false);
String url = "http://oar.nstl.gov.cn/Paper/S ... 3B%3B
try {
HtmlPage htmlPage = browser.getPage(url);
browser.waitForBackgroundJavaScript(3000);
Document document = Jsoup.parse(htmlPage.asXml());
Element paper = document.getElementById("paper");
System.out.println(paper);
} catch (IOException e) {
e.printStackTrace();
}
}
} 查看全部
htmlunit抓取动态网页(.xmlmaven依赖代码
)
今天用jsoup做爬虫的时候发现jsoup只能爬静态页面,对ajax和json动态生成页面的支持不友好。
所以我尝试直接将param和data header随请求一起发送,希望直接返回json数据,但是可能因为网站接口不支持而无法成功。
尝试了其他方法后,从网上发现可以用htmlunit模拟浏览器,生成动态网页,然后用jsoup解析生成的动态网页
以下是pom.xml maven依赖代码
以下是java代码
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import java.io.IOException;
public class JsoupTest {
public static void main(String[] args) {
queryDocument("北斗");
}
public static void queryDocument(String documentName){
WebClient browser = new WebClient();
browser.getOptions().setCssEnabled(false);
browser.getOptions().setJavaScriptEnabled(true);
browser.getOptions().setThrowExceptionOnScriptError(false);
String url = "http://oar.nstl.gov.cn/Paper/S ... 3B%3B
try {
HtmlPage htmlPage = browser.getPage(url);
browser.waitForBackgroundJavaScript(3000);
Document document = Jsoup.parse(htmlPage.asXml());
Element paper = document.getElementById("paper");
System.out.println(paper);
} catch (IOException e) {
e.printStackTrace();
}
}
}
htmlunit抓取动态网页(【K线形态】模拟点击颜色分类,然后读取定价参考(1))
网站优化 • 优采云 发表了文章 • 0 个评论 • 63 次浏览 • 2022-01-22 01:23
通过交互式网络抓取获取天猫商品价格。
方法:模拟点击颜色分类,然后读取定价
参考(1):
主要利用CasperJS工具包:
最重要的是使用css3选择器来选择需要操作的网页的DOM元素。对于 css3 选择器,请参见:
查看元素的提示:
在浏览器上,右键点击对应元素,选择“Inspect Element”,查看对应元素的html代码。
选择器测试提示:
IE或firefox,F12打开开发者窗口,在搜索栏中输入选择器检测选择器效果。
IE:
火狐:
以下代码使用 casperjs tm.js 运行:
var casper = require('casper').create({
clientScripts: ["jquery-1.8.0.js"],
verbose: false,
logLevel: 'debug',
pageSettings: {
loadImages: false, // The WebPage instance used by Casper will
loadPlugins: false // use these settings
}
});
phantom.outputEncoding = "gbk";//解决乱码问题
//获取需要采集的url列表
casper.start('http://detail.tmall.com/item.h ... 39%3B, function() {
console.log(this.getCurrentUrl());
//casper.GetDetailUrl(url);
});
//处理当前页面的所有sku价格与信息
casper.then(function getPic() {
product = casper.evaluate(function getProductFromPage() {
return $('ul[class*="tb-img"]').children().size();
});
console.log(product);
var str = ''
for (var i = 1; i li:nth-child(' + index + ') a');
return index;
};
casper.run();
以上代码参考(1)修改,只实现了给定链接的商品价格的抓取,并在控制台输出。如果要使用node.js抓取链接中的商品在多线程中列出,并通过json将捕获的价格发布到服务器,您可以参考原创方法。 查看全部
htmlunit抓取动态网页(【K线形态】模拟点击颜色分类,然后读取定价参考(1))
通过交互式网络抓取获取天猫商品价格。
方法:模拟点击颜色分类,然后读取定价
参考(1):
主要利用CasperJS工具包:
最重要的是使用css3选择器来选择需要操作的网页的DOM元素。对于 css3 选择器,请参见:
查看元素的提示:
在浏览器上,右键点击对应元素,选择“Inspect Element”,查看对应元素的html代码。
选择器测试提示:
IE或firefox,F12打开开发者窗口,在搜索栏中输入选择器检测选择器效果。
IE:
火狐:
以下代码使用 casperjs tm.js 运行:
var casper = require('casper').create({
clientScripts: ["jquery-1.8.0.js"],
verbose: false,
logLevel: 'debug',
pageSettings: {
loadImages: false, // The WebPage instance used by Casper will
loadPlugins: false // use these settings
}
});
phantom.outputEncoding = "gbk";//解决乱码问题
//获取需要采集的url列表
casper.start('http://detail.tmall.com/item.h ... 39%3B, function() {
console.log(this.getCurrentUrl());
//casper.GetDetailUrl(url);
});
//处理当前页面的所有sku价格与信息
casper.then(function getPic() {
product = casper.evaluate(function getProductFromPage() {
return $('ul[class*="tb-img"]').children().size();
});
console.log(product);
var str = ''
for (var i = 1; i li:nth-child(' + index + ') a');
return index;
};
casper.run();
以上代码参考(1)修改,只实现了给定链接的商品价格的抓取,并在控制台输出。如果要使用node.js抓取链接中的商品在多线程中列出,并通过json将捕获的价格发布到服务器,您可以参考原创方法。
htmlunit抓取动态网页(2019独角兽企业重金招聘Python工程师标准(gt;gt))
网站优化 • 优采云 发表了文章 • 0 个评论 • 57 次浏览 • 2022-01-22 01:18
2019独角兽企业招聘Python工程师标准>>>
最近在做一个项目的时候,有个需求:从一个网页抓取数据,需求是先抓取整个网页的html源码(用于以后的更新)。一开始看到这个简单,然后就匆忙打了代码(之前用的是Hadoop平台的分布式爬虫框架Nutch,用起来很方便,最后因为速度放弃了,但是生成的统计信息用于后续爬取),很快就成功下载了holder.html和finance.html页面,然后解析了holder.html页面后,解析了finance.html,然后很郁闷的在这个页面找到了我需要的东西. 数据不在 html 源代码中。去浏览器查看源码确实是这样的。源代码中确实没有我需要的数据。看来我的程序没有错。- 获取具有动态内容的 html 页面。
在号称国内最强的搜索引擎——百度上走了很久,我发现大部分人都在用WebDriver和HttpUnit(其实前者已经收录了后者)。我很高兴,终于找到了解决方案。. 如此兴奋地使用 WebDriver,我想诅咒。
以下是关于WebDriver的吐槽
WebDriver 是一个测试框架。本来不是为爬虫服务的,但我想说的是:八个字就差一步了,就不能更进一步吗?为什么网上那么多人推荐WebDriver?我觉得这些人不是从现实出发,甚至有人疯狂宣称WebDriver可以解析完成的页面,返回给那些想要爬取整个页面(包括动态生成的内容)的人。是的,WebDriver 可以完成这个任务,但是看到作者写的代码,我想说的是:哥们,你的代码太局限了,解析自己写的js代码,js代码简单,所以WebDriver当然可以毫无压力地完成任务。WebDriver解析动态内容时,取决于js代码的复杂性和多样性。
什么是复杂性?
粘贴一段代码
WebDriver driver = newInternetExplorerDriver ();
HtmlPage page = driver.get(url);
System.out.println(page.asXml());
这段代码的意思相信大家都能看懂。上面使用的IE内核,当然是FirefoxDriver、ChromeDriver、HtmlUnitDriver,使用这些驱动的原理是一样的,先打开浏览器(这需要时间),然后加载url并完成动态解析,然后就可以得到通过page.asXml()完成html页面,其中HtmlUnitDriver模拟无接口浏览器,java有引擎rhino执行js,HtmlUnitDriver使用rhino解析js。它将启动一个带有界面的浏览器,因此 HtmlUnitDriver 比前面三个要快。不管是什么驱动,都难免解析js,这需要时间,而且不同内核对js的支持方案也不一样。例如,HtmlUnitDriver 对带有滚动的 js 代码的支持很差,并且在执行过程中会报错。(亲身经历)。js代码的复杂性意味着不同内核支持的js并不完全相同。这个要根据具体情况来确定。好久没研究js了,就不说各个内核对js的支持了。
什么是多样性
前面说过,浏览器解析js是需要时间的。对于只嵌入少量js代码的页面,通过page.asXml()获取完整页面是没有问题的。但是对于内嵌js代码较多的页面,解析js需要花费很多时间(对于jvm),那么通过page.asXml()获取的页面大部分时间不收录动态生成的内容。的。问题是,为什么说WebDriver可以获取动态内容的html页面呢?网上有人说在driver.get(url)之后,当前线程需要等待一段时间才能拿到完成的页面,类似下面的形式
WebDriver driver = new InternetExplorerDriver();
HtmlPage page = dirver.get(url);
Thread.sleep(2000);
System.output.println(page.asXml());
我根据这个想法尝试了以下,是的,它确实有效。但问题不就在那里吗?如何确定等待时间?类似于数据挖掘中确定阈值的经验方法?,或尽可能长。我觉得这些都不是很好的解决方案,时间成本也比较高。本来以为驱动解析js后应该可以捕获状态,于是就去找找找,但是根本没有这个方法,所以说WebDriver的设计者为什么不走一步forward,这样我们就可以程序获取驱动解析js完成后的状态,所以不需要使用Thread.sleep(2000)等不确定的代码,可惜找不到,真是让我心痛。场。FirefoxDriver,ChromeDriver,HtmlUnitDriver 也有同样的问题。可以说,使用WebDriver辅助爬取到动态生成的网页得到的结果是非常不稳定的。我对此有深刻的理解。在使用IEDriver的时候,同一个页面两次爬取的结果会不一样,有时候IE甚至会直接挂掉。你敢在爬虫程序中使用这样的东西吗?我不敢。
另外,有人推荐使用 HttpUnit。其实WebDirver中的HtmlUnitDriver内部使用的是httpUnit,所以使用HttpUnit也会遇到同样的问题。我也做了一个实验,这是真的。通过Thread.sleep(2000)等待js解析完成,我觉得不可取。不确定性太大,尤其是在大规模爬取工作中。
综上所述,WebDriver 是一个为测试而设计的框架。虽然理论上可以用来辅助爬虫根据其原理获取收录动态内容的html页面,但在实际应用中并没有使用,不确定性太大。稳定性太差,速度太慢,让框架尽其所能吧,不要妥协自己的优势。
我的工作还没有完成,所以我继续上网寻找解决方案。这次找到了一个稳定的、高确定性的辅助工具——phantomjs。目前,我还没有完全理解这个东西。但目前已经用它来实现我想要的。在java中通过runtime.exec(arg)调用phantomjs获取解析js后的页面。我会发布代码
phantomjs端要执行的代码
system = require('system')
address = system.args[1];//获得命令行第二个参数 接下来会用到 //console.log('Loading a web page'); var page = require('webpage').create();
var url = address;
//console.log(url); page.open(url, function (status) {
//Page is loaded!
if (status !== 'success') {
console.log('Unable to post!');
} else {
//此处的打印,是将结果一流的形式output到java中,java通过InputStream可以获取该输出内容 console.log(page.content);
}
phantom.exit();
});
在java端执行的代码
public void getParseredHtml(){
String url = "www.bai.com";
Runtime runtime = Runtime.getRuntime();
runtime.exec("F:/phantomjs/phantomjs/phantomjs.exe F:/js/parser.js "+url);
InputStream in = runtime.getInputStream(); //后面的代码省略,得到了InputStream就好说了 }
这样就可以在java端获取解析后的html页面,而不是像Thread.sleep()这种不确定的代码,需要在WebDriver中使用才能获取可能完成的代码。需要说明一点:phantomjs端的js代码一定不能有语法错误,否则如果js代码编译不同,java端会一直等待,不会抛出异常。再者,使用phantomjs.exe时,java端每次都要开启一个phantomjs进程,耗费大量时间。但至少结果是稳定的。当然,最后我还没有使用phantomjs。我直接下载了自己需要的数据,并没有抓取整个页面,主要是速度问题(其实我对phantomjs不熟悉,所以不敢用,慎用)。
折腾了几天,虽然没有解决我的问题,但还是收获了很多知识。后期的工作就是熟悉phantomjs,看看能不能提高速度。如果能突破限速,以后爬网的时候就得心应手了。此外,Nutch 是框架。我很佩服我的伙伴们在使用它时的便利。后期有必要研究如何优化Nutch on Hadoop的爬取速度。此外,Nutch 原有的功能不会爬行。动态生成的页面内容,不过可以结合Nutch和WebDirver,说不定爬取的结果是稳定的,哈哈,这些只是想法,但是不试试怎么知道呢?
如果园丁对使用WebDriver辅助爬虫得到的结果的稳定性有什么想说的,不客气,因为我确实没有找到相关资料稳定爬取结果。 查看全部
htmlunit抓取动态网页(2019独角兽企业重金招聘Python工程师标准(gt;gt))
2019独角兽企业招聘Python工程师标准>>>

最近在做一个项目的时候,有个需求:从一个网页抓取数据,需求是先抓取整个网页的html源码(用于以后的更新)。一开始看到这个简单,然后就匆忙打了代码(之前用的是Hadoop平台的分布式爬虫框架Nutch,用起来很方便,最后因为速度放弃了,但是生成的统计信息用于后续爬取),很快就成功下载了holder.html和finance.html页面,然后解析了holder.html页面后,解析了finance.html,然后很郁闷的在这个页面找到了我需要的东西. 数据不在 html 源代码中。去浏览器查看源码确实是这样的。源代码中确实没有我需要的数据。看来我的程序没有错。- 获取具有动态内容的 html 页面。
在号称国内最强的搜索引擎——百度上走了很久,我发现大部分人都在用WebDriver和HttpUnit(其实前者已经收录了后者)。我很高兴,终于找到了解决方案。. 如此兴奋地使用 WebDriver,我想诅咒。

以下是关于WebDriver的吐槽
WebDriver 是一个测试框架。本来不是为爬虫服务的,但我想说的是:八个字就差一步了,就不能更进一步吗?为什么网上那么多人推荐WebDriver?我觉得这些人不是从现实出发,甚至有人疯狂宣称WebDriver可以解析完成的页面,返回给那些想要爬取整个页面(包括动态生成的内容)的人。是的,WebDriver 可以完成这个任务,但是看到作者写的代码,我想说的是:哥们,你的代码太局限了,解析自己写的js代码,js代码简单,所以WebDriver当然可以毫无压力地完成任务。WebDriver解析动态内容时,取决于js代码的复杂性和多样性。
什么是复杂性?
粘贴一段代码
WebDriver driver = newInternetExplorerDriver ();
HtmlPage page = driver.get(url);
System.out.println(page.asXml());
这段代码的意思相信大家都能看懂。上面使用的IE内核,当然是FirefoxDriver、ChromeDriver、HtmlUnitDriver,使用这些驱动的原理是一样的,先打开浏览器(这需要时间),然后加载url并完成动态解析,然后就可以得到通过page.asXml()完成html页面,其中HtmlUnitDriver模拟无接口浏览器,java有引擎rhino执行js,HtmlUnitDriver使用rhino解析js。它将启动一个带有界面的浏览器,因此 HtmlUnitDriver 比前面三个要快。不管是什么驱动,都难免解析js,这需要时间,而且不同内核对js的支持方案也不一样。例如,HtmlUnitDriver 对带有滚动的 js 代码的支持很差,并且在执行过程中会报错。(亲身经历)。js代码的复杂性意味着不同内核支持的js并不完全相同。这个要根据具体情况来确定。好久没研究js了,就不说各个内核对js的支持了。
什么是多样性
前面说过,浏览器解析js是需要时间的。对于只嵌入少量js代码的页面,通过page.asXml()获取完整页面是没有问题的。但是对于内嵌js代码较多的页面,解析js需要花费很多时间(对于jvm),那么通过page.asXml()获取的页面大部分时间不收录动态生成的内容。的。问题是,为什么说WebDriver可以获取动态内容的html页面呢?网上有人说在driver.get(url)之后,当前线程需要等待一段时间才能拿到完成的页面,类似下面的形式
WebDriver driver = new InternetExplorerDriver();
HtmlPage page = dirver.get(url);
Thread.sleep(2000);
System.output.println(page.asXml());
我根据这个想法尝试了以下,是的,它确实有效。但问题不就在那里吗?如何确定等待时间?类似于数据挖掘中确定阈值的经验方法?,或尽可能长。我觉得这些都不是很好的解决方案,时间成本也比较高。本来以为驱动解析js后应该可以捕获状态,于是就去找找找,但是根本没有这个方法,所以说WebDriver的设计者为什么不走一步forward,这样我们就可以程序获取驱动解析js完成后的状态,所以不需要使用Thread.sleep(2000)等不确定的代码,可惜找不到,真是让我心痛。场。FirefoxDriver,ChromeDriver,HtmlUnitDriver 也有同样的问题。可以说,使用WebDriver辅助爬取到动态生成的网页得到的结果是非常不稳定的。我对此有深刻的理解。在使用IEDriver的时候,同一个页面两次爬取的结果会不一样,有时候IE甚至会直接挂掉。你敢在爬虫程序中使用这样的东西吗?我不敢。
另外,有人推荐使用 HttpUnit。其实WebDirver中的HtmlUnitDriver内部使用的是httpUnit,所以使用HttpUnit也会遇到同样的问题。我也做了一个实验,这是真的。通过Thread.sleep(2000)等待js解析完成,我觉得不可取。不确定性太大,尤其是在大规模爬取工作中。
综上所述,WebDriver 是一个为测试而设计的框架。虽然理论上可以用来辅助爬虫根据其原理获取收录动态内容的html页面,但在实际应用中并没有使用,不确定性太大。稳定性太差,速度太慢,让框架尽其所能吧,不要妥协自己的优势。
我的工作还没有完成,所以我继续上网寻找解决方案。这次找到了一个稳定的、高确定性的辅助工具——phantomjs。目前,我还没有完全理解这个东西。但目前已经用它来实现我想要的。在java中通过runtime.exec(arg)调用phantomjs获取解析js后的页面。我会发布代码
phantomjs端要执行的代码

system = require('system')
address = system.args[1];//获得命令行第二个参数 接下来会用到 //console.log('Loading a web page'); var page = require('webpage').create();
var url = address;
//console.log(url); page.open(url, function (status) {
//Page is loaded!
if (status !== 'success') {
console.log('Unable to post!');
} else {
//此处的打印,是将结果一流的形式output到java中,java通过InputStream可以获取该输出内容 console.log(page.content);
}
phantom.exit();
});

在java端执行的代码

public void getParseredHtml(){
String url = "www.bai.com";
Runtime runtime = Runtime.getRuntime();
runtime.exec("F:/phantomjs/phantomjs/phantomjs.exe F:/js/parser.js "+url);
InputStream in = runtime.getInputStream(); //后面的代码省略,得到了InputStream就好说了 }

这样就可以在java端获取解析后的html页面,而不是像Thread.sleep()这种不确定的代码,需要在WebDriver中使用才能获取可能完成的代码。需要说明一点:phantomjs端的js代码一定不能有语法错误,否则如果js代码编译不同,java端会一直等待,不会抛出异常。再者,使用phantomjs.exe时,java端每次都要开启一个phantomjs进程,耗费大量时间。但至少结果是稳定的。当然,最后我还没有使用phantomjs。我直接下载了自己需要的数据,并没有抓取整个页面,主要是速度问题(其实我对phantomjs不熟悉,所以不敢用,慎用)。
折腾了几天,虽然没有解决我的问题,但还是收获了很多知识。后期的工作就是熟悉phantomjs,看看能不能提高速度。如果能突破限速,以后爬网的时候就得心应手了。此外,Nutch 是框架。我很佩服我的伙伴们在使用它时的便利。后期有必要研究如何优化Nutch on Hadoop的爬取速度。此外,Nutch 原有的功能不会爬行。动态生成的页面内容,不过可以结合Nutch和WebDirver,说不定爬取的结果是稳定的,哈哈,这些只是想法,但是不试试怎么知道呢?
如果园丁对使用WebDriver辅助爬虫得到的结果的稳定性有什么想说的,不客气,因为我确实没有找到相关资料稳定爬取结果。
htmlunit抓取动态网页(目录1.聚焦爬虫的发展在互联网金融领域应用)
网站优化 • 优采云 发表了文章 • 0 个评论 • 51 次浏览 • 2022-01-21 18:18
导读
马云说,大数据时代已经到来。现在有太多的互联网公司在做大数据,每个公司都有不止一个数据源。占很大比例的数据源之一是网络爬虫。但是,不同的公司有不同的业务背景,需要不同类型的数据。与用于搜索网站的通用爬虫不同,专注爬虫开始被越来越多的提及。
内容
1. 关注爬虫原理
2. 专注于爬虫的开发
3. 爬虫在互联网金融领域的应用
4. 结论
1.专注于爬虫的原理
1.1概念
聚焦爬虫,又称主题爬虫(或专业爬虫),是一种“针对特定主题”的网络爬虫。它与我们通常所说的爬虫(万能爬虫)的区别在于,聚焦爬虫在实现网络爬虫时需要进行主题筛选。它试图确保只抓取与主题相关的网页。
1.2 关注爬虫的分类
焦点爬虫主要分为两类。一种是浅焦点爬虫。所谓浅焦点爬虫,就是爬虫程序抓取特定网站的所有信息。它的工作方式和一般的爬虫几乎一样,唯一不同的是种子URL的选择决定了爬取内容的一致性,核心是种子URL的选择。另一种是深度聚焦爬虫。深度聚焦爬虫是指在大量不同内容的网页中,通过主题相关性算法,选择具有相似主题的URL和内容进行爬取。它的核心是如何判断抓取到的 URL 和页面内容是否与主题相关。
关系如下:
从图中可以看出,浅焦点爬虫可以看成是一种仅限于单一主题网站的通用爬虫,所以我们通常所说的焦点爬虫大多是指深度焦点爬虫。
1.2.1 浅焦点爬虫
浅焦点爬虫从一个或几个初始网页的URL开始,(例如分类信息网)获取初始网页上的URL,在抓取网页的过程中,不断地从原创网页中提取新的URL当前页面并将它们放入队列中,直到系统满意为止。某些停止条件。
其工作流程如下:
可以看出,浅焦点爬虫的基本原理和一般爬虫是一样的。使用主题网站可以保证爬取内容的主题一致。
1.2.2 深度关注爬行动物
Deep Focus Crawler 的主要特点是主题一致性。然而,在浩瀚的互联网大数据海洋中,要保证抓取到的数据的一致性并不是一件简单的事情。对于不同的数据需求,所需的策略和方法没有统一的答案。这里不谈具体的解决方案,只讨论常见的解决方案。
一、对于页面内容
这个解决方案是先爬取页面,不考虑页面的主题。对页面进行简单去噪后,使用主题提取策略提取处理后的页面内容的主题,最后对比设置的主题,如果主题一致,或者在一定的阈值内,则保存页面进行进一步的数据清洗。如果主题偏差超过阈值,则页面被简单地丢弃。
这种方法的优点是链接页面被完全覆盖,不会有数据遗漏。但缺点也很致命,那就是全覆盖页面,其中很大一部分是与主题无关的废弃页面,大大减慢了爬虫爬取数据的速度。到了后期,爬取数据的速度将是无法接受的。
二、对于 URL
上面介绍的浅焦点爬虫的核心是选择合适的种子URL。这些种子 URL 主要是主题 网站 的入口 URL。
网上的网站一般都有固定的主题,同一个网站中相同主题的页面的URL有一定的规律可循。由此,自然而然地产生了通过URL来预测页面主题的想法。另外,页面中的大部分超链接都有锚文本,锚文本基本上可以看作是对目标页面的概括描述。结合对URL的分析和对锚文本的分析,目标页面的话题预测准确率相当可观。
但是,这个预测并不能完全保证丢弃的 URL 都是与主题无关的,因此会有一些遗漏。同时,这种方法不能保证预测的页面都与主题相关,所以需要从预测的URL页面中提取页面内容主题,然后对比设置主题做出选择。
通过以上分析,得到了一个通用的解决方案。就是先通过URL解析,丢弃一些URL。下载页面后,提取页面内容的主题,并与预设的主题进行对比选择。最后进行数据清洗。
1.3 架构
深度聚焦爬虫的一般结构如下:
六大组件【控制中心】【下载模块】【提取模块】【清理模块】【复制模块】【资源模块】
控制模块:控制模块由程序进出、下载调度策略、提取调度策略、清理调度策略和URL重调度策略组成。
下载模块:根据控制中心发送的URL、IP、COOKIE等下载资源下载页面,并将下载结果返回给控制中心。
提取模块:接受控制中心下发的页面源代码和提取指标,根据提取指标提取源代码,并将提取结果返回给控制中心。
清洗模块分为文本清洗和URL清洗。文本清洗根据预设的主题和相应的主题相关性算法决定是丢弃文本还是将文本保存到库中。URL清洗就是根据URL分析结果来预测当前URL链接的页面是否与主题相关。如果相关,则将 URL 返回控制中心,否则丢弃 URL。
URL去重模块:针对部分主题突出的页面被多个页面链接,导致该页面大量重复下载,造成资源浪费和数据质量低下的情况,调用去重模块丢弃重复的 URL 并将非重复的 URL 返回到已下载资源模块的 URL 队列。
资源模块:保存下载所需的所有资源,包括代理IP、COOKIE、URL等信息。
2. 专注于爬虫的开发
大数据时代,对数据的多样性和针对性的要求越来越高。那么爬虫的架构更加灵活多变。比较常见的开源爬虫框架有Crawler4j、WebMagic、WebCollector、scrapy等。另一方面,对于爬虫的爬取,被爬取的网站也制定了相应的反爬措施。常见的反爬虫方法如下:
一、限制对经常访问 网站 的 IP 的访问。这是最常见的释放爬虫的方式。具体实施方式为,单位时间内对同一IP的请求次数达到网站设计的阈值,限制该IP访问。面对这种情况,可以制定合适的IP访问策略。
二、使用js和ajax技术的动态页面。此类网页的源代码中不收录所需的数据,并且该数据包存在于二次请求的返回文档中。对于这样的页面,可以分析请求过程,提取二次请求的URL,得到想要的数据。
三、其他情况:随着互联网的不断发展,各种反爬虫手段层出不穷。这就需要人们根据实际情况来解决问题。比如使用模拟浏览器(htmlunit、selenium)技术等等。
总之,没有不可变的互联网,也没有不可变的爬虫。只有拥抱变化,爬虫才能爬得更远。
3.爬虫在互联网金融领域的应用
聚焦爬虫作为数据的主要来源之一,说一下聚焦爬虫的应用场景,以我任职的普惠金融信息服务(上海)有限公司(以下简称普惠)为例例子。
3.1、网络借贷行业的数据驱动策略
数据驱动就是获取来贷款客户的指定数据,并根据这些数据和相应的一套算法策略为客户定义一个标签。贷款部门根据客户的标签决定是否向客户贷款以及贷款多少。这种定义标签的方式可以有效防止大部分欺诈性贷款的发生,从而规避风险。
那么,网贷平台如何利用大数据来判断客户的信用呢?大致可以分为两个方面:
1、查看此人的购物习惯、客户提供的计费信息等。此方法认为,如果一个人经常在网上购物,有详细的银行对账单,并且有正常的通话记录,那么这个人就是一个正常人,具有一定的财务能力。换句话说,这样的人能够偿还贷款。与发达国家完善的征信体系相比,这种评价方法在我国是可行的,并且在一定时期内是有效的。
2、另一方面,我们认为绝大多数骗子在完成贷款之前不会成为骗子。骗子在贷款之前都是骗子。那么在骗子的行骗生涯中,或多或少都会在网上留下痕迹。比如专门揭露骗子老赖的网站有很多,在一些社交网站上也有很多骗子被针对性曝光。对于这些暴露的数据,平台的大数据中心使用聚焦爬虫进行爬取,然后将爬取的数据保存到黑名单中。
从以上两点可以看出,无论是抓取交易票据等信息,还是抓取暴露的骗子等数据,都离不开聚焦爬虫的应用。
然而,随着互联网的不断发展变化,数据风控人员发现,通过传统方式控制风险越来越难。传统方法爬取的数据,基本上都是属于一个人的点数据,是片面的点数据。什么是点数据?如果把每个人都看成一个整体的数据,那么最形象的结构就是人脉数据网络。每个人都是网络中的一个节点,即每个人的数据都是点状数据。由于个人隐私的原因,我们不能也无法获取一个人的全方位数据,只能截取其中的一个或几个。
使用这些数据来判断一个人的信用等级有两个缺点。一是数据不完整会导致判断不准确。这个缺点是无法避免的。我们只能获取尽可能多的数据,制定更优化的算法模型;其次,随着互联网的发展,点状数据存在更多造假的可能性。例如,如果电子商务的交易记录被故意伪造,很容易产生一批完全符合高信用等级的交易记录。因此,点数据在未来风控体系中的占比会逐渐降低。
对应点数据的不足,爬虫社区有人提出了建立网络数据的可能性。其基本思路是以爬虫为重点,对各大社交网络网站进行爬取,基于这些数据建立人的关系网络,在关系网络的结构中,将补充各个维度的数据添加到每个人中。理想的数据集是每个来平台贷款的人都存在于平台大数据中心的人际关系网络中。我们知道与他们关系密切的人的标签(肖像)。
比如张三来贷款,大数据中心不仅需要知道张三的信用评价,还需要知道与张三关系密切的几个人的信用评价。这有什么用?假设张三的贷款场景如下:张三通过大数据中心的传统信用评价方式获得了良好的信用评价。但我们通过关系网发现,与张三关系密切的人中有不少在信用评价中被评为低信用,甚至被列入黑名单。这时候,我们不得不怀疑张三的数据是否是精心编造的。根据事物就像群体,人是组合在一起的道理,我们认为这种怀疑是必要的。
张三人物关系网络图:
从上图可以看出,张三良好的信用评价并不可靠,贷款会给张三带来很大的风险。显然,传统的风控手段无法避免这种风险,而且这种风险会随着欺诈者对贷款公司信用评估方式的越来越了解而增加。试想,在未来,由于欺诈贷方对公司的风险控制有一个大致的了解,他们在某一方面已经形成了良好的记录。如果大数据中心爬取了这些数据,误判了信用评级,贷款公司所承担的风险将急剧扩大。
鉴于未来这种风险,人脉数据网络提供了解决的可能。如果没有完善可靠的官方征信系统,个人关系数据网络将是未来无抵押贷款公司风控的主流方式。然而,构建人物关系数据网络并不是一朝一夕的事情。
4.结束语
每一个社交网站都有海量数据,与海量数据成正比的是社交网站的反爬虫策略。这对爬虫提出了更高更严格的要求,也细化了不同爬虫之间的差异。然而,不变性并不是互联网的主题。依靠互联网生存的企业必须学会拥抱变化,甚至预测变化,这样才能在未来乘风破浪,越走越远。 查看全部
htmlunit抓取动态网页(目录1.聚焦爬虫的发展在互联网金融领域应用)
导读
马云说,大数据时代已经到来。现在有太多的互联网公司在做大数据,每个公司都有不止一个数据源。占很大比例的数据源之一是网络爬虫。但是,不同的公司有不同的业务背景,需要不同类型的数据。与用于搜索网站的通用爬虫不同,专注爬虫开始被越来越多的提及。
内容
1. 关注爬虫原理
2. 专注于爬虫的开发
3. 爬虫在互联网金融领域的应用
4. 结论
1.专注于爬虫的原理
1.1概念
聚焦爬虫,又称主题爬虫(或专业爬虫),是一种“针对特定主题”的网络爬虫。它与我们通常所说的爬虫(万能爬虫)的区别在于,聚焦爬虫在实现网络爬虫时需要进行主题筛选。它试图确保只抓取与主题相关的网页。
1.2 关注爬虫的分类
焦点爬虫主要分为两类。一种是浅焦点爬虫。所谓浅焦点爬虫,就是爬虫程序抓取特定网站的所有信息。它的工作方式和一般的爬虫几乎一样,唯一不同的是种子URL的选择决定了爬取内容的一致性,核心是种子URL的选择。另一种是深度聚焦爬虫。深度聚焦爬虫是指在大量不同内容的网页中,通过主题相关性算法,选择具有相似主题的URL和内容进行爬取。它的核心是如何判断抓取到的 URL 和页面内容是否与主题相关。
关系如下:
从图中可以看出,浅焦点爬虫可以看成是一种仅限于单一主题网站的通用爬虫,所以我们通常所说的焦点爬虫大多是指深度焦点爬虫。
1.2.1 浅焦点爬虫
浅焦点爬虫从一个或几个初始网页的URL开始,(例如分类信息网)获取初始网页上的URL,在抓取网页的过程中,不断地从原创网页中提取新的URL当前页面并将它们放入队列中,直到系统满意为止。某些停止条件。
其工作流程如下:
可以看出,浅焦点爬虫的基本原理和一般爬虫是一样的。使用主题网站可以保证爬取内容的主题一致。
1.2.2 深度关注爬行动物
Deep Focus Crawler 的主要特点是主题一致性。然而,在浩瀚的互联网大数据海洋中,要保证抓取到的数据的一致性并不是一件简单的事情。对于不同的数据需求,所需的策略和方法没有统一的答案。这里不谈具体的解决方案,只讨论常见的解决方案。
一、对于页面内容
这个解决方案是先爬取页面,不考虑页面的主题。对页面进行简单去噪后,使用主题提取策略提取处理后的页面内容的主题,最后对比设置的主题,如果主题一致,或者在一定的阈值内,则保存页面进行进一步的数据清洗。如果主题偏差超过阈值,则页面被简单地丢弃。
这种方法的优点是链接页面被完全覆盖,不会有数据遗漏。但缺点也很致命,那就是全覆盖页面,其中很大一部分是与主题无关的废弃页面,大大减慢了爬虫爬取数据的速度。到了后期,爬取数据的速度将是无法接受的。
二、对于 URL
上面介绍的浅焦点爬虫的核心是选择合适的种子URL。这些种子 URL 主要是主题 网站 的入口 URL。
网上的网站一般都有固定的主题,同一个网站中相同主题的页面的URL有一定的规律可循。由此,自然而然地产生了通过URL来预测页面主题的想法。另外,页面中的大部分超链接都有锚文本,锚文本基本上可以看作是对目标页面的概括描述。结合对URL的分析和对锚文本的分析,目标页面的话题预测准确率相当可观。
但是,这个预测并不能完全保证丢弃的 URL 都是与主题无关的,因此会有一些遗漏。同时,这种方法不能保证预测的页面都与主题相关,所以需要从预测的URL页面中提取页面内容主题,然后对比设置主题做出选择。
通过以上分析,得到了一个通用的解决方案。就是先通过URL解析,丢弃一些URL。下载页面后,提取页面内容的主题,并与预设的主题进行对比选择。最后进行数据清洗。
1.3 架构
深度聚焦爬虫的一般结构如下:
六大组件【控制中心】【下载模块】【提取模块】【清理模块】【复制模块】【资源模块】
控制模块:控制模块由程序进出、下载调度策略、提取调度策略、清理调度策略和URL重调度策略组成。
下载模块:根据控制中心发送的URL、IP、COOKIE等下载资源下载页面,并将下载结果返回给控制中心。
提取模块:接受控制中心下发的页面源代码和提取指标,根据提取指标提取源代码,并将提取结果返回给控制中心。
清洗模块分为文本清洗和URL清洗。文本清洗根据预设的主题和相应的主题相关性算法决定是丢弃文本还是将文本保存到库中。URL清洗就是根据URL分析结果来预测当前URL链接的页面是否与主题相关。如果相关,则将 URL 返回控制中心,否则丢弃 URL。
URL去重模块:针对部分主题突出的页面被多个页面链接,导致该页面大量重复下载,造成资源浪费和数据质量低下的情况,调用去重模块丢弃重复的 URL 并将非重复的 URL 返回到已下载资源模块的 URL 队列。
资源模块:保存下载所需的所有资源,包括代理IP、COOKIE、URL等信息。
2. 专注于爬虫的开发
大数据时代,对数据的多样性和针对性的要求越来越高。那么爬虫的架构更加灵活多变。比较常见的开源爬虫框架有Crawler4j、WebMagic、WebCollector、scrapy等。另一方面,对于爬虫的爬取,被爬取的网站也制定了相应的反爬措施。常见的反爬虫方法如下:
一、限制对经常访问 网站 的 IP 的访问。这是最常见的释放爬虫的方式。具体实施方式为,单位时间内对同一IP的请求次数达到网站设计的阈值,限制该IP访问。面对这种情况,可以制定合适的IP访问策略。
二、使用js和ajax技术的动态页面。此类网页的源代码中不收录所需的数据,并且该数据包存在于二次请求的返回文档中。对于这样的页面,可以分析请求过程,提取二次请求的URL,得到想要的数据。
三、其他情况:随着互联网的不断发展,各种反爬虫手段层出不穷。这就需要人们根据实际情况来解决问题。比如使用模拟浏览器(htmlunit、selenium)技术等等。
总之,没有不可变的互联网,也没有不可变的爬虫。只有拥抱变化,爬虫才能爬得更远。
3.爬虫在互联网金融领域的应用
聚焦爬虫作为数据的主要来源之一,说一下聚焦爬虫的应用场景,以我任职的普惠金融信息服务(上海)有限公司(以下简称普惠)为例例子。
3.1、网络借贷行业的数据驱动策略
数据驱动就是获取来贷款客户的指定数据,并根据这些数据和相应的一套算法策略为客户定义一个标签。贷款部门根据客户的标签决定是否向客户贷款以及贷款多少。这种定义标签的方式可以有效防止大部分欺诈性贷款的发生,从而规避风险。
那么,网贷平台如何利用大数据来判断客户的信用呢?大致可以分为两个方面:
1、查看此人的购物习惯、客户提供的计费信息等。此方法认为,如果一个人经常在网上购物,有详细的银行对账单,并且有正常的通话记录,那么这个人就是一个正常人,具有一定的财务能力。换句话说,这样的人能够偿还贷款。与发达国家完善的征信体系相比,这种评价方法在我国是可行的,并且在一定时期内是有效的。
2、另一方面,我们认为绝大多数骗子在完成贷款之前不会成为骗子。骗子在贷款之前都是骗子。那么在骗子的行骗生涯中,或多或少都会在网上留下痕迹。比如专门揭露骗子老赖的网站有很多,在一些社交网站上也有很多骗子被针对性曝光。对于这些暴露的数据,平台的大数据中心使用聚焦爬虫进行爬取,然后将爬取的数据保存到黑名单中。
从以上两点可以看出,无论是抓取交易票据等信息,还是抓取暴露的骗子等数据,都离不开聚焦爬虫的应用。
然而,随着互联网的不断发展变化,数据风控人员发现,通过传统方式控制风险越来越难。传统方法爬取的数据,基本上都是属于一个人的点数据,是片面的点数据。什么是点数据?如果把每个人都看成一个整体的数据,那么最形象的结构就是人脉数据网络。每个人都是网络中的一个节点,即每个人的数据都是点状数据。由于个人隐私的原因,我们不能也无法获取一个人的全方位数据,只能截取其中的一个或几个。
使用这些数据来判断一个人的信用等级有两个缺点。一是数据不完整会导致判断不准确。这个缺点是无法避免的。我们只能获取尽可能多的数据,制定更优化的算法模型;其次,随着互联网的发展,点状数据存在更多造假的可能性。例如,如果电子商务的交易记录被故意伪造,很容易产生一批完全符合高信用等级的交易记录。因此,点数据在未来风控体系中的占比会逐渐降低。
对应点数据的不足,爬虫社区有人提出了建立网络数据的可能性。其基本思路是以爬虫为重点,对各大社交网络网站进行爬取,基于这些数据建立人的关系网络,在关系网络的结构中,将补充各个维度的数据添加到每个人中。理想的数据集是每个来平台贷款的人都存在于平台大数据中心的人际关系网络中。我们知道与他们关系密切的人的标签(肖像)。
比如张三来贷款,大数据中心不仅需要知道张三的信用评价,还需要知道与张三关系密切的几个人的信用评价。这有什么用?假设张三的贷款场景如下:张三通过大数据中心的传统信用评价方式获得了良好的信用评价。但我们通过关系网发现,与张三关系密切的人中有不少在信用评价中被评为低信用,甚至被列入黑名单。这时候,我们不得不怀疑张三的数据是否是精心编造的。根据事物就像群体,人是组合在一起的道理,我们认为这种怀疑是必要的。
张三人物关系网络图:
从上图可以看出,张三良好的信用评价并不可靠,贷款会给张三带来很大的风险。显然,传统的风控手段无法避免这种风险,而且这种风险会随着欺诈者对贷款公司信用评估方式的越来越了解而增加。试想,在未来,由于欺诈贷方对公司的风险控制有一个大致的了解,他们在某一方面已经形成了良好的记录。如果大数据中心爬取了这些数据,误判了信用评级,贷款公司所承担的风险将急剧扩大。
鉴于未来这种风险,人脉数据网络提供了解决的可能。如果没有完善可靠的官方征信系统,个人关系数据网络将是未来无抵押贷款公司风控的主流方式。然而,构建人物关系数据网络并不是一朝一夕的事情。
4.结束语
每一个社交网站都有海量数据,与海量数据成正比的是社交网站的反爬虫策略。这对爬虫提出了更高更严格的要求,也细化了不同爬虫之间的差异。然而,不变性并不是互联网的主题。依靠互联网生存的企业必须学会拥抱变化,甚至预测变化,这样才能在未来乘风破浪,越走越远。
htmlunit抓取动态网页(HtmlUnit在多线程环境下怎么使用才能避免网页抓取失败的问题)
网站优化 • 优采云 发表了文章 • 0 个评论 • 65 次浏览 • 2022-01-11 18:06
今天在网上看到一个问题,问如何在多线程环境下使用HtmlUnit,避免网页爬取失败。下面,根据我自己的经验,我将讨论解决这个问题的方法。
这个问题的原因其实很简单。例如,线程 A 正在使用 WebClient 对象来爬取网页。在整个爬取过程结束之前,当前线程被CPU挂起,所以线程B被激活,然后B使用A正在使用的WebClient对象去抓取其他网页,那么这个时候,WebCLient对象就会清除刚刚完成的工作留下的数据,以此类推。共享 WebClient 的线程越多,问题发生的频率就越高。页面丢失的概率也更高。但其实这个问题并不难解决,它的解决方案也有广泛的适用性:无论是任何对象,在多线程环境下遇到资源共享问题时,通常有两种解决方案,
早在JDK1.2版本就提供的java.lang.ThreadLocal和ThreadLocal,为解决多线程程序的并发问题提供了新思路。使用这个工具类,你可以编写精美的多线程程序。这个想法是为每个线程保留变量的本地副本,以确保变量不与其他线程共享 - 一种保守但有效的方法。本文的目的不是介绍ThreadLocal的用法(具体用法请参考百度百科),而是想用ThreadLocal解决多线程环境下HtmlUnit的WebClient对象的共享问题。
请看如何使用 ThreadLocal 对象来解决上述问题:
package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.BrowserVersion;import com.gargoylesoftware.htmlunit.WebClient;/** * * @author Shenghany * @date 2013-5-27 */publicclassThreadLocalClientFactory{//单例工厂模式privatefinalstaticThreadLocalClientFactory instance =newThreadLocalClientFactory();//线程的本地实例存储器,用于存储WebClient实例privateThreadLocal clientThreadLocal;/** * 构造方法,初始时线程的本地变量存储器 */publicThreadLocalClientFactory(){clientThreadLocal =newThreadLocal();}/** * 获取工厂实例 * @return 工厂实例 */publicstaticThreadLocalClientFactory getInstance(){return instance;}/** * 获取一个模拟FireFox3.6版本的WebClient实例 * @return 模拟FireFox3.6版本的WebClient实例 */publicWebClient getClient(){WebClient client =null;/** * 如果当前线程已有WebClient实例,则直接返回该实例 * 否则重新创建一个WebClient实例并存储于当前线程的本地变量存储器 */if((client = clientThreadLocal.get())==null){client =newWebClient(BrowserVersion.FIREFOX_3_6);client.setCssEnabled(false);client.setJavaScriptEnabled(false);clientThreadLocal.set(client);System.out.println("为线程 [ "+Thread.currentThread().getName()+" ] 创建新的WebClient实例!");}else{System.out.println("线程 [ "+Thread.currentThread().getName()+" ] 已有WebClient实例,直接使用. . .");}return client;}}
测试代码:
<p>package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.WebClient;import com.gargoylesoftware.htmlunit.html.HtmlPage;/** * * @author Shenghany * @date 2013-5-27 */publicclassThreadLocalHtmlUnitTester{/** * 获取目标页面,并打印网页标题 * @param url 目标页面地址 */publicstaticvoid getPage(String url){//从工厂中获取一个WebClient实例WebClient client =ThreadLocalClientFactory.getInstance().getClient();try{//抓取网页HtmlPage page =(HtmlPage)client.getPage(url);//打印当前线程名称及网页标题System.out.println(Thread.currentThread().getName()+" [ "+ url +" ] : "+ page.getTitleText());}catch(Exception e){e.printStackTrace();}}/** * 测试程序执行入口 * @param s */publicstaticvoid main(String[] s){//文章编号int postId =50;//目标网页的部分内容String http ="http://www.yshjava.cn/post/4";/** * 共16篇文章,每个线程抓取两篇,共计将产生8个线程 */for(int i = postId; i 查看全部
htmlunit抓取动态网页(HtmlUnit在多线程环境下怎么使用才能避免网页抓取失败的问题)
今天在网上看到一个问题,问如何在多线程环境下使用HtmlUnit,避免网页爬取失败。下面,根据我自己的经验,我将讨论解决这个问题的方法。
这个问题的原因其实很简单。例如,线程 A 正在使用 WebClient 对象来爬取网页。在整个爬取过程结束之前,当前线程被CPU挂起,所以线程B被激活,然后B使用A正在使用的WebClient对象去抓取其他网页,那么这个时候,WebCLient对象就会清除刚刚完成的工作留下的数据,以此类推。共享 WebClient 的线程越多,问题发生的频率就越高。页面丢失的概率也更高。但其实这个问题并不难解决,它的解决方案也有广泛的适用性:无论是任何对象,在多线程环境下遇到资源共享问题时,通常有两种解决方案,
早在JDK1.2版本就提供的java.lang.ThreadLocal和ThreadLocal,为解决多线程程序的并发问题提供了新思路。使用这个工具类,你可以编写精美的多线程程序。这个想法是为每个线程保留变量的本地副本,以确保变量不与其他线程共享 - 一种保守但有效的方法。本文的目的不是介绍ThreadLocal的用法(具体用法请参考百度百科),而是想用ThreadLocal解决多线程环境下HtmlUnit的WebClient对象的共享问题。
请看如何使用 ThreadLocal 对象来解决上述问题:
package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.BrowserVersion;import com.gargoylesoftware.htmlunit.WebClient;/** * * @author Shenghany * @date 2013-5-27 */publicclassThreadLocalClientFactory{//单例工厂模式privatefinalstaticThreadLocalClientFactory instance =newThreadLocalClientFactory();//线程的本地实例存储器,用于存储WebClient实例privateThreadLocal clientThreadLocal;/** * 构造方法,初始时线程的本地变量存储器 */publicThreadLocalClientFactory(){clientThreadLocal =newThreadLocal();}/** * 获取工厂实例 * @return 工厂实例 */publicstaticThreadLocalClientFactory getInstance(){return instance;}/** * 获取一个模拟FireFox3.6版本的WebClient实例 * @return 模拟FireFox3.6版本的WebClient实例 */publicWebClient getClient(){WebClient client =null;/** * 如果当前线程已有WebClient实例,则直接返回该实例 * 否则重新创建一个WebClient实例并存储于当前线程的本地变量存储器 */if((client = clientThreadLocal.get())==null){client =newWebClient(BrowserVersion.FIREFOX_3_6);client.setCssEnabled(false);client.setJavaScriptEnabled(false);clientThreadLocal.set(client);System.out.println("为线程 [ "+Thread.currentThread().getName()+" ] 创建新的WebClient实例!");}else{System.out.println("线程 [ "+Thread.currentThread().getName()+" ] 已有WebClient实例,直接使用. . .");}return client;}}
测试代码:
<p>package cn.ysh.studio.crawler.htmlunit;import com.gargoylesoftware.htmlunit.WebClient;import com.gargoylesoftware.htmlunit.html.HtmlPage;/** * * @author Shenghany * @date 2013-5-27 */publicclassThreadLocalHtmlUnitTester{/** * 获取目标页面,并打印网页标题 * @param url 目标页面地址 */publicstaticvoid getPage(String url){//从工厂中获取一个WebClient实例WebClient client =ThreadLocalClientFactory.getInstance().getClient();try{//抓取网页HtmlPage page =(HtmlPage)client.getPage(url);//打印当前线程名称及网页标题System.out.println(Thread.currentThread().getName()+" [ "+ url +" ] : "+ page.getTitleText());}catch(Exception e){e.printStackTrace();}}/** * 测试程序执行入口 * @param s */publicstaticvoid main(String[] s){//文章编号int postId =50;//目标网页的部分内容String http ="http://www.yshjava.cn/post/4";/** * 共16篇文章,每个线程抓取两篇,共计将产生8个线程 */for(int i = postId; i
htmlunit抓取动态网页(Java环境下的一下配置实现思路介绍-苏州安嘉 )
网站优化 • 优采云 发表了文章 • 0 个评论 • 58 次浏览 • 2022-01-11 17:17
)
爬取网页数据时,传统的jsoup方案只能对静态页面有效,而一些网页数据往往是由js生成的,此时就需要其他的方案了。
第一个思路是分析js程序,再次爬取js请求,适合爬取特定页面,但要实现不同目标url的通用性比较麻烦。
第二种思路,也比较成熟,就是使用第三方驱动渲染页面,然后下载。这是第二个实现思路。
Selenium 是一个模拟浏览器的自动化测试工具。它提供了一组 API 来与真正的浏览器内核交互。
Java环境下的maven配置如下:
org.seleniumhq.selenium
selenium-java
2.46.0
第三方驱动主要有IEDriver、FirefoxDriver、ChromeDriver、HtmlUnitDriver。
htmlUnit 也是一个自动化测试的工具。您可以使用 HtmlUnit 来模拟浏览器运行并获取执行的 html 页面。其中,HtmlUnitDriver是对htmlUnit的封装。
由于htmlunit对js解析的支持有限,在实际项目中并不常用。
以chrome为例,下载对应的驱动:.
下载驱动时,需要注意与selenium版本的兼容性。可能有例外。一般来说,最好下载最新版本。
在运行程序之前,一定要指定驱动位置,比如在Windows下
System.getProperties().setProperty("webdriver.chrome.driver",
"D:\\chromedriver\\chromedriver.exe");
获取整个页面
public static void testChromeDriver() {
System.getProperties().setProperty("webdriver.chrome.driver",
"D:\\chromedriver\\chromedriver.exe");
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://picture.youth.cn/qtdb/2 ... 6quot;);
String responseBody = webDriver.getPageSource();
System.out.println(responseBody);
webDriver.close();
} 查看全部
htmlunit抓取动态网页(Java环境下的一下配置实现思路介绍-苏州安嘉
)
爬取网页数据时,传统的jsoup方案只能对静态页面有效,而一些网页数据往往是由js生成的,此时就需要其他的方案了。
第一个思路是分析js程序,再次爬取js请求,适合爬取特定页面,但要实现不同目标url的通用性比较麻烦。
第二种思路,也比较成熟,就是使用第三方驱动渲染页面,然后下载。这是第二个实现思路。
Selenium 是一个模拟浏览器的自动化测试工具。它提供了一组 API 来与真正的浏览器内核交互。
Java环境下的maven配置如下:
org.seleniumhq.selenium
selenium-java
2.46.0
第三方驱动主要有IEDriver、FirefoxDriver、ChromeDriver、HtmlUnitDriver。
htmlUnit 也是一个自动化测试的工具。您可以使用 HtmlUnit 来模拟浏览器运行并获取执行的 html 页面。其中,HtmlUnitDriver是对htmlUnit的封装。
由于htmlunit对js解析的支持有限,在实际项目中并不常用。
以chrome为例,下载对应的驱动:.
下载驱动时,需要注意与selenium版本的兼容性。可能有例外。一般来说,最好下载最新版本。
在运行程序之前,一定要指定驱动位置,比如在Windows下
System.getProperties().setProperty("webdriver.chrome.driver",
"D:\\chromedriver\\chromedriver.exe");
获取整个页面
public static void testChromeDriver() {
System.getProperties().setProperty("webdriver.chrome.driver",
"D:\\chromedriver\\chromedriver.exe");
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://picture.youth.cn/qtdb/2 ... 6quot;);
String responseBody = webDriver.getPageSource();
System.out.println(responseBody);
webDriver.close();
}
htmlunit抓取动态网页(1.HtmlUnit的学习方法是什么?怎么样?HtmlUnit)
网站优化 • 优采云 发表了文章 • 0 个评论 • 59 次浏览 • 2022-01-10 20:07
1.HtmlUnit 是一个用java 编写的无界面浏览器,它可以模拟html 文档、通过API 调用页面、填写表单、点击链接等等。像普通浏览器一样运行。通常用于测试和从网页中抓取信息。而HtmlUnit有HttpClient和soup的功能,但是速度比较慢,但是如果取消它解析css和js的功能,速度也会有所提升,默认开启。
2.这里,HtmlUnit是用来爬取数据的,主要是为了获取他的js和css。
3.主要代码如下
package com.los;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.los.util.DownlandPic;
import java.io.IOException;
import java.util.regex.Pattern;
public class HtmlUnitTest {
public static void main(String[] args) throws IOException {
DownlandPic dd = new DownlandPic();
WebClient webClient = new WebClient();//实例化web客户端
//http://www.bdqn.cn/ https://www.baidu.com/?tn=78000241_22_hao_pg
String url = "http://www.bdqn.cn/";
HtmlPage page = webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000); //等侍js脚本执行完成
System.out.println(page.asXml());
DomNodeList img = page.getElementsByTagName("script");
for (int i=0;i 0) {
output.write(buffer, 0, length);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static int getCharacterPosition3(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 2){
break;
}
}
return slashMatcher.start();
}
public static int getCharacterPosition4(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 3){
break;
}
}
return slashMatcher.start();
}
public static void main(String[] args) {
String content = "<img class=\"lazy\" data-original=\"/img/newImg/news_img2.jpg\" src=\"/img/newImg/news2.jpg\" style=\"display: block;\"/>";
System.out.println(getCharacterPosition3(content));
System.out.println(getCharacterPosition4(content));
String substring = content.substring(getCharacterPosition3(content), getCharacterPosition4(content));
System.out.println(substring);
}
}
3.因为这里网页中的图片地址是相对路径,所以下载的时候到页面中找到它的绝对路径,拼接在下载地址中。下载的路径必须与图片标签中的地址对应爬取后存储在本地页面,否则无法找到。
3.之所以在匹配“时写2和3是根据这里爬取的数据。
4.相对于其他爬取网页的写法,这个可能更简单,但是更能体现效果。如有错误,请多多指教。至于页面不会显示,涉及隐私。
5.了解HtmlUnit请参考:地址 查看全部
htmlunit抓取动态网页(1.HtmlUnit的学习方法是什么?怎么样?HtmlUnit)
1.HtmlUnit 是一个用java 编写的无界面浏览器,它可以模拟html 文档、通过API 调用页面、填写表单、点击链接等等。像普通浏览器一样运行。通常用于测试和从网页中抓取信息。而HtmlUnit有HttpClient和soup的功能,但是速度比较慢,但是如果取消它解析css和js的功能,速度也会有所提升,默认开启。
2.这里,HtmlUnit是用来爬取数据的,主要是为了获取他的js和css。
3.主要代码如下
package com.los;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.los.util.DownlandPic;
import java.io.IOException;
import java.util.regex.Pattern;
public class HtmlUnitTest {
public static void main(String[] args) throws IOException {
DownlandPic dd = new DownlandPic();
WebClient webClient = new WebClient();//实例化web客户端
//http://www.bdqn.cn/ https://www.baidu.com/?tn=78000241_22_hao_pg
String url = "http://www.bdqn.cn/";
HtmlPage page = webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000); //等侍js脚本执行完成
System.out.println(page.asXml());
DomNodeList img = page.getElementsByTagName("script");
for (int i=0;i 0) {
output.write(buffer, 0, length);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static int getCharacterPosition3(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 2){
break;
}
}
return slashMatcher.start();
}
public static int getCharacterPosition4(String string){
//这里是获取"\""符号的位置
Matcher slashMatcher = Pattern.compile("\"").matcher(string);
int mIdx = 0;
while(slashMatcher.find()) {
mIdx++;
//当"/"符号第三次出现的位置
if(mIdx == 3){
break;
}
}
return slashMatcher.start();
}
public static void main(String[] args) {
String content = "<img class=\"lazy\" data-original=\"/img/newImg/news_img2.jpg\" src=\"/img/newImg/news2.jpg\" style=\"display: block;\"/>";
System.out.println(getCharacterPosition3(content));
System.out.println(getCharacterPosition4(content));
String substring = content.substring(getCharacterPosition3(content), getCharacterPosition4(content));
System.out.println(substring);
}
}
3.因为这里网页中的图片地址是相对路径,所以下载的时候到页面中找到它的绝对路径,拼接在下载地址中。下载的路径必须与图片标签中的地址对应爬取后存储在本地页面,否则无法找到。
3.之所以在匹配“时写2和3是根据这里爬取的数据。

4.相对于其他爬取网页的写法,这个可能更简单,但是更能体现效果。如有错误,请多多指教。至于页面不会显示,涉及隐私。
5.了解HtmlUnit请参考:地址
htmlunit抓取动态网页(搜索引擎更喜欢静态页面还是动态页面之前?(图))
网站优化 • 优采云 发表了文章 • 0 个评论 • 57 次浏览 • 2022-01-10 10:07
项目投资找A5快速获取精准代理商名单
做网站优化,到底是静态页面好还是动态页面好,一直是众多优化者争论不休的问题。有的站长说搜索引擎喜欢抓取一些静态页面,就像野兽在打猎的时候,总是喜欢先抓到不动的难缠的物体,而这些站长认为静态页面在搜索引擎的猛兽眼中. 所以。
在知道搜索引擎更喜欢静态页面还是动态页面之前,有必要普及一下网站的基础知识:什么是静态页面?简单来说就是页面的URL不收录一些动态元素,比如“?,%,&”,那么只要页面URL地址中收录这些元素,就称为动态页面。
从上面的意思我们知道,静态页面和动态页面最大的区别在于是否收录一些动态元素,而这些动态元素会导致搜索引擎蜘蛛无法理解早期的搜索引擎。以为是多个不同的URL,就会不断爬取这个动态的URL地址,造成“搜索引擎蜘蛛黑洞”。
所以早期的搜索引擎真的不喜欢动态页面,更喜欢抓取静态页面。但随着搜索引擎技术的不断发展,历届各大搜索引擎公司都宣称可以爬取和爬取动态页面,对动态页面和静态页面一视同仁,包括谷歌、百度、搜搜。
说一下我个人的看法,由于搜索引擎的进步,动态页面也可以被爬取,爬得很好。因此,当 URL 中的动态元素尽可能少时,可以使用动态页面。这里给你举个例子,.***.net/wp-login.php?redirect_to=http%3A%2F%2F###.net%2Fwp-admin%2F&reauth=1,很明显是一个URL URL动态网页,但收录的动态元素太多,对搜索引擎不友好,不可用。
。***。网/?p=167,这种网址也是动态的,如果只收录一个“?”,很多搜索引擎都可以抓取到。我自己也用这种动态网址做了几个网站,一段时间后,几个网站的收录和排名都很好。所以到底搜索引擎更喜欢静态页面还是动态页面,我觉得应该差不多吧。 查看全部
htmlunit抓取动态网页(搜索引擎更喜欢静态页面还是动态页面之前?(图))
项目投资找A5快速获取精准代理商名单
做网站优化,到底是静态页面好还是动态页面好,一直是众多优化者争论不休的问题。有的站长说搜索引擎喜欢抓取一些静态页面,就像野兽在打猎的时候,总是喜欢先抓到不动的难缠的物体,而这些站长认为静态页面在搜索引擎的猛兽眼中. 所以。
在知道搜索引擎更喜欢静态页面还是动态页面之前,有必要普及一下网站的基础知识:什么是静态页面?简单来说就是页面的URL不收录一些动态元素,比如“?,%,&”,那么只要页面URL地址中收录这些元素,就称为动态页面。
从上面的意思我们知道,静态页面和动态页面最大的区别在于是否收录一些动态元素,而这些动态元素会导致搜索引擎蜘蛛无法理解早期的搜索引擎。以为是多个不同的URL,就会不断爬取这个动态的URL地址,造成“搜索引擎蜘蛛黑洞”。
所以早期的搜索引擎真的不喜欢动态页面,更喜欢抓取静态页面。但随着搜索引擎技术的不断发展,历届各大搜索引擎公司都宣称可以爬取和爬取动态页面,对动态页面和静态页面一视同仁,包括谷歌、百度、搜搜。
说一下我个人的看法,由于搜索引擎的进步,动态页面也可以被爬取,爬得很好。因此,当 URL 中的动态元素尽可能少时,可以使用动态页面。这里给你举个例子,.***.net/wp-login.php?redirect_to=http%3A%2F%2F###.net%2Fwp-admin%2F&reauth=1,很明显是一个URL URL动态网页,但收录的动态元素太多,对搜索引擎不友好,不可用。
。***。网/?p=167,这种网址也是动态的,如果只收录一个“?”,很多搜索引擎都可以抓取到。我自己也用这种动态网址做了几个网站,一段时间后,几个网站的收录和排名都很好。所以到底搜索引擎更喜欢静态页面还是动态页面,我觉得应该差不多吧。
htmlunit抓取动态网页(抓一个今日头条的首页内容解决方案-苏州安嘉)
网站优化 • 优采云 发表了文章 • 0 个评论 • 82 次浏览 • 2022-01-08 13:06
不知道大家在使用jsoup的过程中是否遇到过爬取内容,发现有些网页中的内容是通过javascript异步加载的,导致我们的爬虫空手返回(只抓一个网页的外框) .
当我第一次遇到这个问题时,我想到了两个解决方案:
在等待网页异步加载后,使用类似于 Python 中延迟加载的方法对异步加载的网页进行爬取。使用一种特殊的方法来模拟被爬取的网页框架内的 JavaScript 代码的执行,最终到达完整的网页。
在搜索引擎的帮助下,决定使用方案二来解决这个问题。解决方案1中没有搜索到更好的第三方库。在java中使用解决方案1解决此问题的朋友希望与下一个讨论,非常感谢。
案例很简单,抓取一条今日头条的首页内容。你可以看一下今日头条的首页,里面的内容是异步加载的。
添加jsoup和htmlunit依赖
org.jsoup
jsoup
1.10.2
net.sourceforge.htmlunit
htmlunit
2.25
12345678910
首先,我们单独使用jsoup来解析今日头条的首页
String url = "https://www.toutiao.com/";
Connection connect = Jsoup.connect(url);
Document document = connect.get();
System.out.println(document);
1234
↑ 这里只能获取网页的框架内容,不能获取首页的新闻内容
接下来,我们使用htmlunit来尝试
//构造一个webClient 模拟Chrome 浏览器
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//屏蔽日志信息
LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log",
"org.apache.commons.logging.impl.NoOpLog");
java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
//支持JavaScript
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setActiveXNative(false);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setTimeout(5000);
HtmlPage rootPage = webClient.getPage(url);
//设置一个运行JavaScript的时间
webClient.waitForBackgroundJavaScript(5000);
String html = rootPage.asXml();
Document document = Jsoup.parse(html);
12345678910111213141516171819
<a target="_blank" style="box-sizing: border-box; color: rgb(12, 137, 207);"></a>
这为我们提供了一个运行 JavaScript 的完整源页面 查看全部
htmlunit抓取动态网页(抓一个今日头条的首页内容解决方案-苏州安嘉)
不知道大家在使用jsoup的过程中是否遇到过爬取内容,发现有些网页中的内容是通过javascript异步加载的,导致我们的爬虫空手返回(只抓一个网页的外框) .
当我第一次遇到这个问题时,我想到了两个解决方案:
在等待网页异步加载后,使用类似于 Python 中延迟加载的方法对异步加载的网页进行爬取。使用一种特殊的方法来模拟被爬取的网页框架内的 JavaScript 代码的执行,最终到达完整的网页。
在搜索引擎的帮助下,决定使用方案二来解决这个问题。解决方案1中没有搜索到更好的第三方库。在java中使用解决方案1解决此问题的朋友希望与下一个讨论,非常感谢。
案例很简单,抓取一条今日头条的首页内容。你可以看一下今日头条的首页,里面的内容是异步加载的。
添加jsoup和htmlunit依赖
org.jsoup
jsoup
1.10.2
net.sourceforge.htmlunit
htmlunit
2.25
12345678910
首先,我们单独使用jsoup来解析今日头条的首页
String url = "https://www.toutiao.com/";
Connection connect = Jsoup.connect(url);
Document document = connect.get();
System.out.println(document);
1234
↑ 这里只能获取网页的框架内容,不能获取首页的新闻内容
接下来,我们使用htmlunit来尝试
//构造一个webClient 模拟Chrome 浏览器
WebClient webClient = new WebClient(BrowserVersion.CHROME);
//屏蔽日志信息
LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log",
"org.apache.commons.logging.impl.NoOpLog");
java.util.logging.Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
//支持JavaScript
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setActiveXNative(false);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setTimeout(5000);
HtmlPage rootPage = webClient.getPage(url);
//设置一个运行JavaScript的时间
webClient.waitForBackgroundJavaScript(5000);
String html = rootPage.asXml();
Document document = Jsoup.parse(html);
12345678910111213141516171819
<a target="_blank" style="box-sizing: border-box; color: rgb(12, 137, 207);">

这为我们提供了一个运行 JavaScript 的完整源页面