- 浏览: 214827 次
- 来自: ...
文章分类
最新评论
-
nbh219:
插件只有这几行代码吗jQuery.fn.dataTableEx ...
在Datatables中加入错误提示功能 -
radio123:
好用,谢了!就是有一点问题,如果DataGird 有分页栏,会 ...
JQuery Easy UI —— 如何让DataGrid自适应页面宽度 -
loafer:
这种方式是将工程发布为war还是ear?因为以前也这样写过,但 ...
Weblogic 10.3.6 解决Jar包冲突,hibernate等。 -
springdata:
spring data jpa相关代码demo下载:http: ...
Spring Data JPA 使用感受 -
coolboy09:
楼主,能否给个完整的例子?在下在用jqplot绘图时,在添加了 ...
jqPlot 实现动态显示数据,防止内存溢出的实现。
最近三年很少写博客,虽然一直从事IT行业,但更多的是管理工作,想想真有些惭愧。
最近半年,时不时业务上需要爬虫,将网页内容爬取分析,有用于AI人工智能分析,有用于大数据分析,种种应用,发现爬虫作用不小
这篇文章不是一篇教学文章,更多的是分享在爬取网页中可能会遇到的一些技术问题以及常见问题,并提供解决方案。因此更适合有一定爬虫开发经验人员阅读。
虽然本文使用Java,但这些常见问题,与所使用的开发语言无关,可更多借鉴。
常见问题一:网页的获取方式
1、直接获取静态页面方式
何为“静态页面”,指页面内容通过HTTP获取的时候,已经是完整页面内容,没有使用Ajax异步调用生成页面内容的网页,即页面内容均在后台生成。
仅对该类页面,使用基于HTTP方式直接加载页面时,才可以获取完整页面内容。
对于Java语言,可以使用JSoup或者HttpClient去抓取,页面获取效率非常高。下面提供参考源码:
JSoup方式:
HttpClient方式:
HttpClient依赖:
JSoup依赖:
2、使用模拟浏览器方式获取动态页面
使用模拟浏览器的方式实属被逼无奈,因为这种方式处理速度实在是慢,但对于异步加载内容的网页特别有效。如果你发现直接通过Http拉取页面获取不到元素值的时候,也只能使用这种方法。
HtmlUnit获取网页:
HtmlUnit依赖:
常见问题二:如何避免IP被封
处理方式比较简单,就是不要使用并发,或者连续性的长时间抓取网站内容。最好抓取的时候,保持一定的时间间隔,根据我抓取不同网站的经验,间隔在3-5秒获取一次网页最为保险,一些网站一旦封了IP,可能要一周左右才解锁,因此对于固定外网IP的用户,正在大规模抓取之前必须留意该限制。
以下抓取代码供参考:
那么如何提升抓取效率呢?一般网站,都会根据Session以及IP进行锁定是否DDOS攻击,或者恶意刷网页,所以问题也就简单了,通过多个线程发起请求,保证每个Session请求的间隔时间。另外,并发也不要太过分,只要不对网站造成压力,一般不会被封IP。
常见问题三:对于元素选取的问题
获取元素的方式有很多种方法,可以通过ID、CSS样式、元素类型(比如<a/> <p/>)等,可根据个人喜好,通常都可以获得元素的内容,比如文章标题、文章正文等等。
以下分享我个人使用JSoup获取页面元素内容的一些心得。
1、阶梯式获取
即优先优先获取顶级节点,比如<Content>是文章内容的顶级节点,那么通过JSoup先获取 第一个顶级节点,然后再获取下级节点的内容,避免当存在多个<Content>节点的时候,会出现获取内容超出预期。
2、CSS样式的选取问题
当存在多个class样式,比如:<div class="css1 css2">...</div>,使用JSoup选取:
使用点号连在一起即可。
最近半年,时不时业务上需要爬虫,将网页内容爬取分析,有用于AI人工智能分析,有用于大数据分析,种种应用,发现爬虫作用不小
这篇文章不是一篇教学文章,更多的是分享在爬取网页中可能会遇到的一些技术问题以及常见问题,并提供解决方案。因此更适合有一定爬虫开发经验人员阅读。
虽然本文使用Java,但这些常见问题,与所使用的开发语言无关,可更多借鉴。
常见问题一:网页的获取方式
1、直接获取静态页面方式
何为“静态页面”,指页面内容通过HTTP获取的时候,已经是完整页面内容,没有使用Ajax异步调用生成页面内容的网页,即页面内容均在后台生成。
仅对该类页面,使用基于HTTP方式直接加载页面时,才可以获取完整页面内容。
对于Java语言,可以使用JSoup或者HttpClient去抓取,页面获取效率非常高。下面提供参考源码:
JSoup方式:
/** * 获取游记文章页面的HTML对象。 * * @param articleUrl * 文章URL地址。 * @return * @throws IOException */ private Document getArticleDocument(String articleUrl) throws IOException { Connection conn = Jsoup.connect(articleUrl); conn.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0"); Response rs = conn.execute(); Document doc = Jsoup.parse(rs.body()); return doc; }
HttpClient方式:
/** * 直接通过HTTP请求获取页面内容。 * * @param url * @return * @throws ClientProtocolException */ public static String getUrlHtml(String url) throws ClientProtocolException, IOException { HttpClient httpclient = HttpClientBuilder.create().build(); HttpGet httpGet = new HttpGet(url); httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; W…) Gecko/20100101 Firefox/56.0"); httpGet.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); httpGet.setHeader("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4"); httpGet.setHeader("Accept-Encoding", "gzip, deflate, sdch"); httpGet.setHeader("Upgrade-Insecure-Requests", "1"); HttpResponse response1 = httpclient.execute(httpGet); HttpEntity entity = response1.getEntity(); String html = EntityUtils.toString(entity); return html; }
HttpClient依赖:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency>
JSoup依赖:
<dependency> <!-- jsoup HTML parser library @ https://jsoup.org/ --> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.10.3</version> </dependency>
[color=red] 此处需要特别强调,对于很多网站,对爬虫都有一定的防范,因此在获取页面时,必须要补齐浏览器信息,否则很容易会导致被封IP! [/color]
2、使用模拟浏览器方式获取动态页面
使用模拟浏览器的方式实属被逼无奈,因为这种方式处理速度实在是慢,但对于异步加载内容的网页特别有效。如果你发现直接通过Http拉取页面获取不到元素值的时候,也只能使用这种方法。
HtmlUnit获取网页:
/** * 通过模拟浏览器的方式下载完整页面。 * * @param url * @return * @throws FailingHttpStatusCodeException * @throws IOException */ public static String downloadHtml(String url, int timeout) throws FailingHttpStatusCodeException, IOException { try (final WebClient webClient = new WebClient(BrowserVersion.CHROME)) { webClient.getOptions().setJavaScriptEnabled(true); webClient.getOptions().setCssEnabled(false); webClient.getOptions().setRedirectEnabled(true); webClient.getOptions().setThrowExceptionOnScriptError(false); webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); webClient .setAjaxController(new NicelyResynchronizingAjaxController()); webClient.getOptions().setTimeout(timeout); WebRequest webRequest = new WebRequest(new URL(url)); webRequest.setHttpMethod(HttpMethod.GET); final HtmlPage page = webClient.getPage(webRequest); webClient.waitForBackgroundJavaScriptStartingBefore(500); webClient.waitForBackgroundJavaScript(20000); final String pageAsXml = page.asXml(); return pageAsXml; } }
HtmlUnit依赖:
<dependency> <groupId>net.sourceforge.htmlunit</groupId> <artifactId>htmlunit</artifactId> <version>2.30</version> </dependency>
常见问题二:如何避免IP被封
处理方式比较简单,就是不要使用并发,或者连续性的长时间抓取网站内容。最好抓取的时候,保持一定的时间间隔,根据我抓取不同网站的经验,间隔在3-5秒获取一次网页最为保险,一些网站一旦封了IP,可能要一周左右才解锁,因此对于固定外网IP的用户,正在大规模抓取之前必须留意该限制。
以下抓取代码供参考:
/* * (non-Javadoc) * * @see * com.hna.tech.spider.service.SpiderService#setPageArticleDetail(java.lang * .String) */ public List<Map<String, String>> setPageArticleDetail( List<Map<String, String>> pageList) throws IOException, InterruptedException { for (Map<String, String> item : pageList) { [color=red] // 最小延迟3秒,少于3秒将可能被封IP Thread.sleep(3000); [/color] String articleUrl = item.get(KEY_LINK); Document doc = getArticleDocument(articleUrl); String articleHtml = getArticleContentHtml(doc); item.put(KEY_CONTENT_HTML, articleHtml); String articleContent = getArticleContent(doc); item.put(KEY_CONTENT, articleContent); } return pageList; }
那么如何提升抓取效率呢?一般网站,都会根据Session以及IP进行锁定是否DDOS攻击,或者恶意刷网页,所以问题也就简单了,通过多个线程发起请求,保证每个Session请求的间隔时间。另外,并发也不要太过分,只要不对网站造成压力,一般不会被封IP。
常见问题三:对于元素选取的问题
获取元素的方式有很多种方法,可以通过ID、CSS样式、元素类型(比如<a/> <p/>)等,可根据个人喜好,通常都可以获得元素的内容,比如文章标题、文章正文等等。
以下分享我个人使用JSoup获取页面元素内容的一些心得。
1、阶梯式获取
即优先优先获取顶级节点,比如<Content>是文章内容的顶级节点,那么通过JSoup先获取 第一个顶级节点,然后再获取下级节点的内容,避免当存在多个<Content>节点的时候,会出现获取内容超出预期。
2、CSS样式的选取问题
当存在多个class样式,比如:<div class="css1 css2">...</div>,使用JSoup选取:
doc.select("div.css1.css2")
使用点号连在一起即可。
发表评论
-
亲测国外很快的Maven镜像
2016-11-23 14:29 4988亲测速度非常理想,并且不会像阿里的镜像很多包下载不下来。在自己 ... -
再谈Java获取classepath路径问题
2016-08-09 14:04 0网上很多文章介绍如何获取Java的classpath路径,这里 ... -
禁用HTML超链接URL的双击
2015-05-26 10:30 1080有时候我们希望控制用户在点击URL超链接的时候,只允许点击一次 ... -
根据时间段查询log日志,拆分日志等
2014-12-23 09:02 1651示例一: 日志格式: wechat_Log:[2014-09- ... -
Java中判断文件是否是图片文件
2014-08-17 23:20 18291使用Image读取文件时,如果是非图像文件,则会返回null。 ... -
Weblogic 10.3.6 解决Jar包冲突,hibernate等。
2014-07-06 16:30 7441Weblogic的jar包冲突困扰了我一段时间,一般使用的是如 ... -
javascript 动态显示家庭人物结构关系图
2014-01-07 23:53 7124<!DOCTYPE html PUBLIC &quo ... -
Jquery EasyUI中级篇
2013-12-23 16:08 2358JQuery EasyUI是一个很不错的Javascript开 ... -
JavaScript中,快速实现一个对象的复制!
2013-03-01 15:28 10761、第一种方式,通过JSON转换。 function cl ... -
Java路径问题解决方案汇集
2013-02-17 13:54 1566最近查看了网上很多关于路径问题资料大概总结了一下: Java ... -
EasyUI中,DataGrid的错误处理方式。
2013-02-06 17:06 0话说,JQuery EasyUI是一个非常优秀的JQuery框 ... -
再议JQuery中Ajax内存溢出问题。
2013-01-29 12:05 5853发现有人挺感兴趣Javascript中的内存溢出,本人经验发现 ... -
最近好新闻不断
2012-12-14 08:36 1015Spring Framework 3.2 GA 发布 ... -
Java中通过POI读取Excel 2003 - 2007的xls,xlsx格式
2012-12-01 21:01 5447@Test public void testRead ... -
对jqplot的CategoryAxisRenderer插件进行扩展,底部Tick在鼠标在上时浮动显示名称。
2012-11-30 09:04 3457在前一篇文章中介绍了如何让jqplot的柱形图tick下标出现 ... -
zTree 如何自动选中节点
2012-11-20 13:40 6258下列代码可以使用在弹出树或者动态选中树的节点时使用: ... -
对jqplot的CategoryAxisRenderer插件进行扩展,让文字出现省略号
2012-10-19 15:45 2946喜欢用jqplot的朋友一定碰到图形下标文字很长,会出现相互之 ... -
在Datatables中加入错误提示功能
2012-10-08 17:32 15384经常用Datatables的童鞋一定碰到过当采用服务端请求的时 ... -
jqplot 实用技巧——重绘
2012-09-18 08:46 4377技巧一: 当浏览器窗体大小改变时: $('#resizab ... -
jqPlot 实现动态显示数据,防止内存溢出的实现。
2012-09-12 16:06 6574jqPlot是一个十分强大、 ...
相关推荐
综上所述,"基于网络爬虫技术的网络新闻分析"项目不仅提供了实际的编程经验,还涵盖了网络爬虫技术、数据库管理、系统设计和软件工程的多个方面,对Java初学者和毕业设计的学生来说是一个极好的实践平台。...
在创建索引的时候,需要将网页的URL和网页的内容传到相应的方法中,当然URL和内容是要对应的,也许是经验太少吧,我采取的是通过构建一个JavaBean的方式来传递的,不知道大家有没有更好的方法 2.关于要创建...
总的来说,这个Java爬虫项目实战不仅涵盖了基础的网络爬虫技术,还涉及到许多高级特性和实战经验。通过学习和实践,你可以掌握从零开始构建一个功能完备的Java爬虫,并具备处理复杂网络环境的能力。无论是为了工作...
Python合法网页爬虫工具项目分享 内容概览: 这个分享包涵了我开发的Python爬虫工具项目,主要用于合法爬取某些网页信息。以下是主要内容: 源代码:包括Python代码和相关脚本。这些代码展示了如何使用Python进行...
知乎是一个知名的中文在线问答社区,汇聚了众多领域的专家和用户,分享知识、经验和见解。为了分析、研究或获取知乎上的数据,开发者可能会编写这样的爬虫工具。 首先,我们要明确爬虫的基本原理。网络爬虫通常由...
图书大数据爬虫部分,主要讲解如何利用网络爬虫技术获取图书相关的数据,这可能包括图书的元信息、用户评论、销售数据等。Python的Scrapy框架或者Java的Jsoup库是常见的选择,它们可以帮助我们高效地抓取和解析网页...
CSDN是中国最大的IT技术社区,程序员们在这里分享技术文章、交流编程经验。 首先,这个程序的核心功能是网络爬虫。网络爬虫是通过模拟浏览器行为抓取网页内容的程序。在这个Java版本的实现中,程序会发送HTTP请求到...
访问这个链接可以获取更深入的了解,包括代码示例、使用方法以及作者的经验分享。 【标签】:“源码 工具” 这两个标签暗示了这个项目不仅提供了源代码,而且可能是一个实用工具。源码意味着我们可以查看并学习到...
在找寻“Python爬虫工程师实习生”的过程中,这位求职者分享了他的一些经历和面试体验。以下是关于Python爬虫工程师实习岗位的相关知识点: 1. **实习时间与工作日**: 实习生通常需要与公司协商实习期间的工作时间...
通过下载和学习,你可以深入了解JAVA如何实现抓图功能,并从中获得实践经验。 【标签】:“抓图程序说明 PPT” 标签“抓图程序说明”表明了这个教程的核心内容,即解释如何创建和使用抓图程序。而“PPT”标签则...
描述中的“NULL”没有提供具体信息,但根据提供的博文链接,我们可以推测这可能是一个博客文章,讨论了作者对Java工具的一些见解或者分享了一种特定的Java工具的使用经验。由于链接无法直接访问,我们无法获取详细...
随着互联网技术的发展,网络爬虫作为一项重要的数据收集手段,在各行各业中的应用越来越广泛。对于初学者来说,如何快速掌握爬虫开发技能并找到实用的项目案例至关重要。本文将详细介绍可以从哪些途径获取到高质量的...
2. **项目经验**:列出你在Java Web开发、爬虫工程或大数据处理等方面的项目经历。描述项目目标、使用的技术栈、你的职责以及项目成果。这能展示你的实际操作能力和项目管理能力。 3. **技术技能**:详列你的技术...
3. **Python爬虫实战** - 崔庆才的博客,分享了许多实战经验和技巧,对于进阶学习很有帮助。 ### 结语 通过以上介绍,我们可以了解到Python爬虫的基础知识、常用工具和库、注意事项以及一些实用的学习资源。爬虫...
面试全套通常包括技术面试题、算法和数据结构练习、项目经验分享和软技能培养。对于技术面试,了解基本的算法(如排序和搜索)、复杂度分析和设计模式是必不可少的。同时,良好的沟通能力和问题解决能力同样重要。 ...
在线预览项目地址:在线...将自己对该系统的理解和实践经验分享给他人,促进技术互动和知识共享。 其他说明: 源代码系统基于JAVA开发,具备良好的可扩展性和可维护性。开发者可以根据实际需求进行二次开发和定制。
总的来说,"Arachnid_src.zip_Arachnid"不仅是一个网络爬虫的实例,更是一个学习网络爬虫技术和资源分享的宝贵教材。通过深入研究这个项目,我们可以深化对网络爬虫的理解,提高编程技能,并且能更好地适应日新月异...
- 拥有一个庞大且活跃的开发者社区,用户可以轻松获得技术支持、分享经验和解决问题。 6. **易于扩展**: - 支持与其他语言集成,如 C 或 C++,通过扩展模块提高性能或实现特定功能。 7. **开源**: - Python ...
【注意:用户使用须知1】的描述涵盖了多个IT知识点,包括Java开发...总的来说,这个项目涉及到Java编程、数据库管理、网络依赖、IDE使用以及项目维护等多个IT技能,用户需要具备一定的技术背景和操作经验才能顺利使用。
Python 因其强大的库支持以及简洁易读的语法特性,在网络爬虫开发领域受到了广泛欢迎。本文将从以下几个方面详细介绍 Python 网页爬虫的基础知识: 1. **抓取网页的接口与工具** 2. **网页抓取后的处理** 3. **爬虫...