java爬虫抓取网页图片如何处理重复抓取的网页

本文参与,欢迎正在阅读的你也加入,一起分享。|95 篇文章23 人订阅相关文章来自专栏18来自专栏31来自专栏14来自专栏25来自专栏29来自专栏16JAVA使用爬虫抓取网站网页内容的方法
转载 &发布时间:日 09:36:05 & 作者:fzhlee
这篇文章主要介绍了JAVA使用爬虫抓取网站网页内容的方法,实例分析了java爬虫的两种实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
本文实例讲述了JAVA使用爬虫抓取网站网页内容的方法。分享给大家供大家参考。具体如下:
最近在用JAVA研究下爬网技术,呵呵,入了个门,把自己的心得和大家分享下
以下提供二种方法,一种是用apache提供的包.另一种是用JAVA自带的.
// 第一种方法
//这种方法是用apache提供的包,简单方便
//但是要用到以下包:commons-codec-1.4.jar
// commons-httpclient-3.1.jar
// commons-logging-1.0.4.jar
public static String createhttpClient(String url, String param) {
HttpClient client = new HttpClient();
String response =
String keyword =
PostMethod postMethod = new PostMethod(url);
if (param != null)
keyword = new String(param.getBytes("gb2312"), "ISO-8859-1");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
// NameValuePair[] data = { new NameValuePair("keyword", keyword) };
// // 将表单的值放入postMethod中
// postMethod.setRequestBody(data);
// 以上部分是带参数抓取,我自己把它注销了.大家可以把注销消掉研究下
int statusCode = client.executeMethod(postMethod);
response = new String(postMethod.getResponseBodyAsString()
.getBytes("ISO-8859-1"), "gb2312");
//这里要注意下 gb2312要和你抓取网页的编码要一样
String p = response.replaceAll("//&[a-zA-Z]{1,10};", "")
.replaceAll("&[^&]*&", "");//去掉网页中带有html语言的标签
System.out.println(p);
} catch (Exception e) {
e.printStackTrace();
// 第二种方法
// 这种方法是JAVA自带的URL来抓取网站内容
public String getPageContent(String strUrl, String strPostRequest,
int maxLength) {
// 读取结果网页
StringBuffer buffer = new StringBuffer();
System.setProperty("sun.net.client.defaultConnectTimeout", "5000");
System.setProperty("sun.net.client.defaultReadTimeout", "5000");
URL newUrl = new URL(strUrl);
HttpURLConnection hConnect = (HttpURLConnection) newUrl
.openConnection();
// POST方式的额外数据
if (strPostRequest.length() & 0) {
hConnect.setDoOutput(true);
OutputStreamWriter out = new OutputStreamWriter(hConnect
.getOutputStream());
out.write(strPostRequest);
out.flush();
out.close();
// 读取内容
BufferedReader rd = new BufferedReader(new InputStreamReader(
hConnect.getInputStream()));
for (int length = 0; (ch = rd.read()) & -1
&& (maxLength &= 0 || length & maxLength); length++)
buffer.append((char) ch);
String s = buffer.toString();
s.replaceAll("//&[a-zA-Z]{1,10};", "").replaceAll("&[^&]*&", "");
System.out.println(s);
rd.close();
hConnect.disconnect();
return buffer.toString().trim();
} catch (Exception e) {
// return "错误:读取网页失败!";
然后写个测试类:
public static void main(String[] args) {
String url = "http://www.jb51.net";
String keyword = "脚本之家";
createhttpClient p = new createhttpClient();
String response = p.createhttpClient(url, keyword);
// 第一种方法
// p.getPageContent(url, "post", 100500);//第二种方法
呵呵,看看控制台吧,是不是把网页的内容获取了
希望本文所述对大家的java程序设计有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具基于网络爬虫工作原理,该如何优化SEO-筑龙博客
办公空间室内设计&营业厅室内设计&展览展示室内设计
基于网络爬虫工作原理,该如何优化SEO
1.1 爬虫定义 & &爬虫是一个抓取网页的计算机程序,它在互联网中漫游,发现和搜集信息。日夜不停地运行,尽可能多、尽可能快地搜集各种类型的新信息,同时因为互联网上的信息更新很快,所以还要定期更新已经搜集过的旧信息,以避免死连接和无效连接。 & 1.2 第一个爬虫 & RBSE (Eichmann,1994)是第一个发布的爬虫。它有两个基础程序。第一个是“spider”,抓取队列中的内容到一个关系数据库中,第二个程序是“mite”,是一个修改后的www的ASCII浏览器,负责从网络上下载页面。 & &1.3 日常生活接触 & Baiduspider, Googlebot。 &1.2 爬虫组成 & 网络爬虫主要由控制器,解析器,资源库组成。 中央控制器:根据系统传过来的URL链接,分配一线程,启动线程调用爬虫爬取网页。 & 解析器:是爬虫的主要部分,负责下载网页,对网页的文本进行处理,如过滤功能,抽取特殊HTML标签的功能,分析数据功能。 & 资源库:主要是用来存储网页中下载下来的数据记录的容器,并提供生成索引的目标源。中大型的数据库产品有:Oracle、Sql Server等。 & 1.3 爬虫类型 & 一般分传统爬虫和聚集爬虫。 & (1)传统爬虫,从一个或若干初始网页的URL开始,获得初始网页上的URL,抓取之后,通过源码解析来获得想要的内容。 & (2)聚焦爬虫:根据一定的网页分析算法过滤与主题无关的链接,重复上述过程,直到达到系统的某一条件时停止所有被爬虫抓取的网页将会被系统存贮。 & 2.抓取对象 & &抓取对象:静态网页、文件对象、动态网页、特殊内容。 & 特殊内容:比如RSS、XML数据,情况特殊需特殊处理。如新闻的滚动新闻页面,需要爬虫不停地监控扫描,发现新内容马上就进行抓取。 & 3.爬虫成本 & &使用爬虫的代价包括: & (1)网络资源:在很长一段时间,爬虫使用相当的带宽高度并行地工作。 & (2)服务器超载:尤其是对给定服务器的访问过高时。 & (3)逻辑糟糕的爬虫,可能导致服务器或者路由器瘫痪,或者会尝试下载自己无法处理的页面。 & &个人爬虫,如果过多的人使用,可能导致网络或者服务器阻塞。 & 4. 爬虫质量www.ds798.cn www.szyoudun.com www.power-motor.cn www.gdmcd168.com www.xyfdiy.cn
ysw2015的最新博文
分享到微信朋友圈
打开微信"扫一扫",扫描上方二维码请点击右上角按钮&,选择&
同时发布一条微博
$(".zhul_sy_rightBox").popupbox({geturl:ucenterDomain+"openjson/getpopupbox",format:"bigright",cssClass:"zhul_info_rightbox",waithtml:' '});
$().zlidol({geturl:weiboDomain+"userinfo/jsonidol?action=idol"})
})(jQuery);浅谈动态爬虫与去重
预估稿费:600RMB(不服你也来投稿啊!)
投稿方式:发送邮件至,或登陆在线投稿
随着Web 2.0的发展,页面中的AJAX也越来越多。由于传统爬虫依靠静态分析,不能准确的抓取到页面中的AJAX请求以及动态更新的内容,已经越来越不能满足需求。基于动态解析的Web 2.0爬虫应运而生,通过浏览器内核解析页面源码,模拟用户操作,能有效解决上述问题。本文将详细分析利用PhantomJS + Python 编写爬虫并进行去重的思路。
0x02 PhantomJS
是无界面的 Webkit 解析器,提供了 JavaScript API 。由于去除了可视化界面,速度比一般 Webkit 浏览器要快很多。同时提供了很多监控和事件接口,可以方便的操作 DOM 节点,模拟用户操作等。
接下来我们通过一个简单的例子,来展示下动态爬虫和传统爬虫的区别。目标:加载一个页面(),并且获取其中所有的&a&标签。
// example.js
var page = require('webpage').create();
page.onAlert = function (message) {
console.log(message);
page.onCallback = function() {
page.evaluate(function(){
atags = document.getElementsByTagName("a");
for(var i=0;i&atags.i++){
if (atags[i].getAttribute("href")){
alert(atags[i].getAttribute("href"));
phantom.exit()
page.open("http://named.cn/.mine", "get", "", function (status) {
page.evaluateAsync(function(){
if (typeof window.callPhantom === 'function') {
window.callPhantom();
抓取结果如下:
/cmd2/controls/signin
/cmd2/controls/getcode
/download.html
/~发现推荐.findbbs
/help.html
/江南水乡.bbs/7313348
/摄情男女.bbs/7313242
/欢乐一家亲.bbs/7313356
/深夜食堂.bbs/7313168
/家有熊孩子.bbs/7313321
/乐淘亲子营.bbs/7313320
.../*省略*/...
/婚礼记.bbs/7277165
/不知道的事情.bbs/7277164
/不知道的事情.bbs/7277162
/婚礼记.bbs/7277160
/不知道的事情.bbs/7277016
http://www.miitbeian.gov.cn/
/cmd2/controls/mailpost/内容举报
download.html
静态抓取的代码如下:
import requests
import pyquery
res = requests.get("http://named.cn/.mine")
pq = pyquery.PyQuery(res.content)
for i in pq("a"):
print "[%d]: %s" % (count, pq(i).attr("href"))
抓取结果为空。
从上述的例子中,我们可以明显看出动态分析比静态分析抓取到了更多的结果。产生差别的原因,是页面中的数据加载来自于AJAX请求,所有的 &a& 标签都是动态更新到页面中的。静态分析对这种情况无能为力,而基于浏览器内核的动态分析,可以轻松的处理这些情况。
但也可以明显看出动态分析的缺点:系统资源占用较多,且占用时间较长,还会有一些莫名其妙的坑,编写起来也更复杂更花时间(需要对前端编程有一定的了解)。
当然除了 PhantomJS 还有一些其他的动态解析器,比如同样基于 Webkit 内核的 PyQt(PhantomJS的最新版本也是基于pyqt来实现)、基于 PhantomJS 封装的 CasperJS、基于的 Firefox Gecko 内核的SlimerJS等。由于并没有一个统一的标准,各个动态解析器的API实现程度也参差不齐,也会有各种各样的坑,并没有一个 “最佳” 的解决方案。
0x03 触发事件及页面监听
上面的例子,介绍了爬虫中常见的一个场景:在页面加载完成后,通过AJAX加载数据。但现实中的场景,往往会更复杂,需要与用户进行交互后才会触发,比如在点击了某个按钮后跳转到某个页面、滚动到页面尾部后加载下一页的数据等。我们需要新的解决方案,去模拟正常用户的操作。那么,应该如何将用户交互抽象为代码?
用户操作的本质,实际上是触发了绑定在DOM节点的事件。所以模拟用户操作的问题,可以简化为触发节点事件。事件执行的结果也是多种多样的,但对于爬虫来说,我们需要关注的结果只有两种:1. 是否添加了新的节点(&a&、&iframe&等等) 2. 是否发起了新的请求(包括AJAX请求、跳转等)。简化后,我们需要解决的问题有:
1. 如何获取绑定事件?
2. 如何触发事件?
3. 如何获取事件触发的结果?
最后我们的解决方案如下:
1. 如何获取绑定事件?JavaScript中绑定事件,都会调用addEventListener函数。在页面里的代码执行前(),hook addEventListener函数,就可以捕获到哪些DOM节点绑定了事件。
_addEventListener = Element.prototype.addEventL
Element.prototype.addEventListener = function(a,b,c) {
EVENT_LIST.push({"event": event, "element": this})
_addEventListener.apply(this, arguments);
2. 如何触发事件?JavaScript中提供了dispatchEvent函数,可以触发指定DOM节点的指定事件,也就是上一个问题中,我们收集的EVENT_LIST。
for(var i in EVENT_LIST){
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(EVENT_LIST[i]["event"], true, true, null);
EVENT_LIST[i]["element"].dispatchEvent(evt);
除了通过addEventListener绑定事件,还有一些inline-script,是无法通过hook addEventListener来获取的。比如:
&div id="test" onclick="alert('hello')"&&/div&
解决方法是遍历节点,执行所有的onxxxx属性的值。
function trigger_inline(){
var nodes = document.
for (var i = 0; i & nodes. i++) {
var attrs = nodes[i].
for (var j = 0; j & attrs. j++) {
attr_name = attrs[j].nodeN
attr_value = attrs[j].nodeV
if (attr_name.substr(0, 2) == "on") {
console.log(attrs[j].nodeName + ' : ' + attr_value);
eval(attr_value);
if (attr_name in {"src": 1, "href": 1} && attrs[j].nodeValue.substr(0, 11) == "javascript:") {
console.log(attrs[j].nodeName + ' : ' + attr_value);
eval(attr_value.substr(11));
3. 如何获取事件触发的结果?HTML5中的MutationObserver方法,可以检查页面中的DOM是否发生变化。但是PhantomJS并不支持(摊手 ),解决方案是监听了DOMNodeInserted事件。AJAX请求的捕获,解决方案有两种: 可以捕获非主框架的请求,但需要通过正则表达式匹配筛选出有效请求;hook XMLHttpRequest.open 和 XMLHttpRequest.send 可以准确的捕获请求内容。
document.addEventListener('DOMNodeInserted', function(e) {
var node = e.
if(node.src || node.href){
LINKS_RESULT.push(node.src || node.href);
_open = XMLHttpRequest.prototype.open
XMLHttpRequest.prototype.open = function (method, url) {
if (!this._url) {
this._url =
this._method =
_open.apply(this, arguments);
_send = XMLHttpRequest.prototype.send
XMLHttpRequest.prototype.send = function (data) {
window.$Result$.add_ajax(this._url, this._method, data);
_send.apply(this, arguments);
整理一下,在页面加载前,需要hook三个接口:addEventListener、XMLHttpRequest.open、XMLHttpRequest.send。页面加载完之后,需要获取所有的&a&、&iframe&、&form&标签,开启页面DOM节点监听,并且触发所有的事件。最后输出结果。
在实现了动态爬取的基本功能后,还有一些可以提升爬虫的稳定性和效率的小tips:自动填写表单(应对某些情况下参数为空导致表单无法提交)、禁止非必要资源的加载(jpg、png、css、mp4等)、页面加载完成后禁止跳转(防止因为触发事件导致的跳转)、hook会导致页面阻塞的函数(alert、prompt)、触发事件向下冒泡(解决一些不标准的前端代码绑定的DOM节点太宽泛导致的问题,但实测非常影响效率)等。
去重是爬虫中最核心,也是最影响爬虫效率和结果的部分。去重过于粗放,在遇到页面比较多的网站时爬不完。过于严格的话,爬取的结果太少,也会影响后续扫描的效果。
去重一般分为两个部分:任务队列的去重、结果队列的去重。这两种去重的区别在于,在爬虫运行过程中,任务队列是一直变动的(增加 & 减少),而结果队列是不断的增加的。对任务队列的去重,要在扫描过程中重复的进行的,即某个页面爬取完成后,获取的结果加入任务队列进行下一次爬虫任务之前,需要做一次去重(或者每完成一个深度的爬虫任务,进行一次去重),而结果队列是在所有的任务结束后进行去重,不影响爬虫运行效率,只影响最后的结果输出。这两种去重可以使用相同的去重策略,也可以使用不同的策略(对任务队列的去重,可以根据当前的任务量,进行去重力度的调整)。
我们将爬虫的功能和需求程度逐一列出来:
1. 基础: 非抓取目标站点的URL
2. 基础: 完全重复的URL & 参数打乱但实际上仍然重复的URL
3. 温饱: 分析参数,去除遍历型的,exp: page.php?id=1、page.php?id=2 等
4. 温饱: 支持伪静态URL去重
5. 小康: 奇形怪状URL的去重,exp: test.php?a=1?b=2?from=233、 test.php?a=1?b=3?from=test
6. 小康: 根据当前的任务量,动态调整去重力度
前两个基础需求实现起来比较简单,将域名、参数列表提取出来进行对比就可以了,一次循环解决问题。
第三个需求,需要匹配参数值,比如: int、hash、中文、URL编码等。需要注意的是,不可以直接用匹配的方式处理英文的参数值。如:
http://test.com/index.php?m=home&c=test&a=view
http://test.com/index.php?m=home&c=test&a=add
其中m、c、a参数分别代表了不同的module、controller、action,属于“ 功能型参数 ”,需要保留。功能性参数的值在大多数情况下是字母(有意义的单词),有些情况下也会是数字或者数字字母的混合。那么,应该如何做策略?
这个问题目前的解决方案也比较粗暴,对全部是字母的参数值,不做处理,对数字字母混合的参数值,根据任务量的多少进行“ 弹力去重 ”(详见需求6)。举个实际的例子:
# 去重处理前:
http://test.com/index.php?m=home&c=test&id=3
http://test.com/index.php?m=home&c=test&type=friday
http://test.com/index.php?m=home&c=test&type=464730bbd7fbffd597f2808f
http://test.com/index.php?m=home&c=test&type=b59c67bf196af76670ceba
# 处理过程:
{"m": "home", "c": "test", "id":"{{int}}"}
{"m": "home", "c": "test", "id":"{{int}}"}
{"m": "home", "c": "test", "type":"friday"}
{"m": "home", "c": "test", "type":"{{hash}}"}
{"m": "home", "c": "test", "type":"{{hash}}"}
# 去重结果:
http://test.com/index.php?m=home&c=test&id=2
http://test.com/index.php?m=home&c=test&type=friday
http://test.com/index.php?m=home&c=test&type=464730bbd7fbffd597f2808f
第四个需求,支持伪静态去重。首先要定义对路径去重的策略,我们把路径用/分隔开,扔到处理参数值的函数中去处理(符合规则的替换为指定字符串、不符合规则的原样返回),然后再用替换过的URL做去重处理就可以了。当然还有一些伪静态长这样:
htttp://xxx.com/?index_1_test_233
htttp://xxx.com/?index_1_new_456
再按照上述的去重策略就过于粗略,应该怎么处理呢?继续往下看。
第五个需求,奇形怪状的URL。目前已有的去重策略都是通过分析替换参数值、路径名来实现的,但是这种奇奇怪怪的URL根本不按套路出牌,只能采用非常的方法:在参数、路径进行拆分处理前,替换掉一些干扰字符。举个实例:
http://test.com/test.php?id=12?from=te?user=233
http://test.com/test.php?id=12?from=te?user=233_abc
http://test.com/test.php?id={{int}}?from=te?user={{int}}
http://test.com/test.php?id={{int}}?from=te?user={{mix_str}}
第六个需求,根据当前的任务量,自动调整去重策略。在有些情况下,上述的各种去重套路都不好用,比如:
http://test.com/user.php?name=test
http://test.com/user.php?name=今天是阴天
http://test.com/user.php?name=bbbbb
当用户名为自定义,且有成千上万个用户的时候,上述的去重策略就都失效了。问题出在哪里?
需求三的解决方案似乎过于粗略了,直接把所有的纯英文字符串放过了,但是也没有更好的解决方案。只能针对这种特殊情况,再加一次循环,先找到出现次数过多的参数,再针对这些特定的参数进行强制去重。新的策略是这样的:第一次循环只进行预处理,分析当前的参数列表,并计数。第二遍,根据参数列表的计数值判断当前参数是否需要强制去重。举个实例:
http://test.com/index.php?name=friday&m=read
http://test.com/index.php?name=test&m=read
http://test.com/index.php?name=2333&m=read
# 第一轮遍历结果
md5(name+m):{count:3, "name":["friday","test","{{int}}"], "m": ["read"]},
当参数列表相同的URL数量大于某个特定值,且某个参数的值的个数大于某个特定值的时候,强制对该参数进行去重,即将全英文字符串替换为{{str}}。
上述方法实现起来稍微有点儿绕,还有个粗暴点儿的解决方案:不去检测具体参数,只判断当前任务队列里的任务数是否超过某个值,一旦超过,就启动强制去重(只要参数列表或根路径相同,直接去掉,可能会误杀很多伪静态)。
在实现了上述的六个需求后,一个简洁有效的去重脚本就完成了,流程图如下:
为了测试动态爬虫(以下简称KSpider)的基本功能和效率,选取了同样是基于动态分析的WVS扫描器的爬虫(以下简称WVSSpider)来对比。
首先测试基本抓取功能。提供了几个demo,爬取结果如下:
# 注: WVSSpider无法设置爬虫深度及线程数,针对path相同的url会进行聚合处理,生成SiteFile。
WVSSpider # wvs_console.exe /Crawl http://demo.aisec.cn/demo/aisec/ /SaveLogs /SaveFolder C:UsersxxxDesktop /ExportXML
Request Count: 31, SiteFile Count: 11, Time Count: 23
KSpider # python crawler.py http://demo.aisec.cn/demo/aisec/ {"depth": 5, "thread_count": 5}
Request Count: 23, Result Count: 18, Time Cost: 33
KSpider Basic # python crawler.py http://demo.aisec.cn/demo/aisec/ {"depth": 5, "thread_count": 5, "type": "basic"}
Request Count: 11,
Result Count: 8, Time Cost: 1
前两个扫描都抓取到了5个关键的请求,包括:
基础&a&标签: http://demo.aisec.cn/demo/aisec/html_link.php?id=2
JS自动解析: http://demo.aisec.cn/demo/aisec/js_link.php?id=2&msg=abc
JS自动解析 + FORM表单: http://demo.aisec.cn/demo/aisec/post_link.php
JS自动解析 + AJAX请求: http://demo.aisec.cn/demo/aisec/ajax_link.php?id=1&t=0.51955
事件触发 + DOM改变: http://demo.aisec.cn/demo/aisec/click_link.php?id=2
静态分析的扫描速度很快,但只扫出了上述5个请求中的第一个。通过表单分析抓取到了第三个POST请求,但是由于&form&表单中的&input&标签是由JavaScript动态生成(代码如下),所以没有抓取到请求的具体参数。
&form method="post" name="form1" enctype="multipart/form-data" action="post_link.php"&
document.write('&input type="text" name="i'+'d" size="30" value=1&&br&');
document.write('&input type="text" name="m'+'sg" size="30" value="abc"&');
&input type="submit" value="提交" name="B1"&
接下来是爬虫的效率测试,抓取目标是 。结果如下:
WVSSpider # wvs_console.exe /Crawl https://tieba.baidu.com /SaveLogs /SaveFolder C:UsersxxxDesktop /ExportXML
Request Count: 201, SiteFile Count: 101, Time Count: 220
KSpider # python crawler.py https://tieba.baidu.com {"depth": 5, "thread_count": 10}
Request Count: 410, Result_length: 535, Time_Cost: 339
可以看到,随着网站复杂度的上升,WVS爬虫的请求数增长相对平稳,而KSpider在线程数为10的情况下,在6分钟内也完成了爬取任务,表现正常。
在分析过程中,虽然 WVSSpider 速度很快,整体效率非常高,但也有一些缺点:爬取深度无法指定、无法跨平台工作、对于伪静态形式的URL去重效果较差(如下图所示的SiteFile共有43个,占比42%)、爬虫结果中有部分URL分割结果(如:https://tieba.baidu.com/home/main?un=111 会分割成两个SiteFile,/home 和 /home/main,所以实际扫描到的URL数量比结果要少)等。
由于目标网站URL较多,覆盖率比较难测算,我们用脚本简单对比了 WVSSpider 和 KSpider 抓取的结果,除去静态资源,KSpider 覆盖了98%的 WVSSpider 抓取结果(即 WVSSpider 抓取结果里,有98%的结果同样被 KSpider 抓到),而 WVSSpider 仅覆盖了38%的 KSpider 抓取结果。
除了以上提到的去重和动态解析,还有一些小tips,如fuzz常见路径、从robots.txt中提取信息、爬取过程中进行敏感信息识别、生成网站信息画像等,对爬虫的覆盖率及后续的扫描任务会有帮助。
本文详细的介绍了在动态爬虫的实现过程中,可能会遇到的问题以及解决方案。优秀的代码不会一蹴而就,需要持续的优化调整,后期会考虑开源,欢迎沟通交流。
这个人太懒了,签名都懒得写一个Google 爬虫如何抓取 Javascript 的?
稿源:伯乐在线
我们测试了谷歌爬虫是如何抓取 JavaScript,下面就是我们从中学习到的知识。
认为 Google 不能处理 JavaScript ?再想想吧。Audette Audette 分享了一系列测试结果,他和他同事测试了什么类型的&JavaScript 功能会被 Google 抓取和收录。
1. 我们进行了一系列测试,已证实&Google 能以多种方式执行和收录&JavaScript。我们也确认 Google 能渲染整个页面并读取 DOM,由此能收录动态生成的内容。
2. DOM 中的 SEO 信号(页面标题、meta 描述、canonical 标签、meta robots 标签等)都被关注到。动态插入 DOM 的内容都也能被抓取和收录。此外,在某些案例中,DOM 甚至可能比 HTML 源码语句更优先。虽然这需要做更多的工作,但这是我们好几个测试中的一个。
引言:Google 执行 JavaScript & 读取 DOM
早在 2008 年, Google 就&成功抓取 JavaScript,但很可能局限于某种方式。
而在今天,可以明确的是,Google 不仅能制定出他们抓取和收录的 JavaScript 类型,而且在渲染整个 web 页面上取得了显著进步(特别在最近的 12 到 18 个月)。
在 Merkle,我们的 SEO 技术团队想更好地理解谷歌爬虫能抓取和收录什么类型的 JavaSscript 事件。经过研究,我们发现令人瞠目的结果,并已证实 Google 不仅能执行各种 JavaScript 事件,而且能收录动态生成的内容。怎么样做到的?Google 能读取 DOM。
DOM 是什么?
很多搞 SEO 的都不理解什么是&Document Object Model(DOM)。
当浏览器请求页面时会发生什么,而 DOM 又是如何参与进来的。
当用于 web 浏览器,DOM 本质上是一个应用程序的接口,或 API,用于标记和构造数据(如 HTML 和 XML)。该接口允许 web 浏览器将它们进行组合而构成文档。
DOM 也定义了如何对结构进行获取和操作。虽然 DOM 是与语言无关的 API (不是捆绑在特定编程语言或库),但它普遍应用于 web 应用程序的 JavaScript 和 动态内容。
DOM 代表了接口,或&桥梁&,将&web 页面与编程语言连接起来。解析 HTML 和执行 JavaScript 的结果就是 DOM。web 页面的内容不(不仅)是源码,是 DOM。这使它变得非常重要。
JavaScript&是如何通过 DOM 接口工作的。
我们兴奋地发现 Google 能够读取 DOM,并能解析信号和动态插入的内容,例如 title 标签、页面文本、head 标签和 meta 注解(如:rel = canonical)。可阅读其中的完整细节。
关于这一系列测试、及结果
因为想知道什么样的 JavaScript 功能会被抓取和收录,我们单独对 谷歌爬虫 创建一系列测试。通过创建控件,确保 URL 活动能被独立理解。下面,让我们详细划分出一些有趣的测试结果。它们被分为 5 类:
JavaScript 重定向
JavaScript 链接
动态插入内容
动态插入 Meta 数据 和页面元素
一个带有 rel = &nofollow& 的重要例子
例子:一个用来测试谷歌爬虫理解 JavaScript 能力的页面。
1. JavaScript 重定向
我们首先测试了常见的 JavaScript 重定向,用不同方式表示的&URL 会有什么样结果呢?我们选择了 window.location&对象进行两个测试:Test A 以绝对路径 URL 调用 window.location,而 Test B 使用相对路径。
结果:该重定向很快被 Google 跟踪。从收录来看,它们被解释为 301 -&最终状态的 URL 取代了 Google 收录里的重定向 URL。
在随后的测试中,我们在一个权威网页上,利用完全相同的内容,完成一次利用&JavaScript 重定向到同一个站点的新页面。而原始 URL 是排在 Google 热门查询的首页。
结果:果然,重定向被 Google 跟踪,而原始页面并没有被收录。而新 URL 被收录了,并立刻排在相同查询页面内的相同位置。这让我们很惊喜,以排名的角度上看,视乎表明了JavaScript 重定向行为(有时)很像永久性的 301 重定向。
下次,你的客户想要为他们的网站完成 JavaScript 重定向移动,你可能不需要回答,或回答:&请不要&。因为这似乎有一个转让排名信号的关系。支持这一结论是引用了 Google 指南:
使用 JavaScript 为用户进行重定向,可能是一个合法的做法。例如,如果你将已登录用户重定向到一个内部页面,你可以使用 JavaScript 完成这一操作。当仔细检查 JavaScript 或其他重定向方法时,以确保你的站点遵循我们的指南,并考虑到其意图。记住 301 重定向跳转到你网站下是最好的,但如果你没有权限访问你网站服务器,你可以为此使用 JavaScript 重定向。
有好的文章希望站长之家帮助分享推广,猛戳这里
本网页浏览已超过3分钟,点击关闭或灰色背景,即可回到网页

我要回帖

更多关于 爬虫抓取动态网页数据 的文章

 

随机推荐