最近三年很少写博客,虽然一直从事IT行业,但更多的是管理工作,想想真有些惭愧。
最近半年,时不时业务上需要爬虫,将网页内容爬取分析,有用于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")
使用点号连在一起即可。
相关推荐
### va_start、va_end、va_list的详细使用方法 #### 概述 在C语言中,函数参数的数量通常是固定的。然而,在某些情况下,我们可能希望一个函数能够接收可变数量的参数。例如,`printf`函数就是一个很好的例子,它...
### stdarg.h中三个宏va_start,va_arg和va_end的应用详解 在C语言中,经常需要编写能够接受可变数量参数的函数。一个典型的例子就是`printf`函数,它可以接受任意数量和类型的参数。为了支持这种功能,C语言提供了...
近年来,逐渐开放的微软加快了 Visual Studio 的演进速度,持续地吸收了不少 VA 的特性,但多年的积累使得 VA 的对应实现仍有着很强的竞争力。就拿代码重构里最基本的“重命名”来说,VA Rename 就比 VS Rename 步骤...
《Visual Assistant VA_X-2366:提升Visual Studio C++编程效率的得力助手》 Visual Assistant VA_X是一款专...无论是新手还是经验丰富的开发者,都能从中受益。如果你是一名C++开发者,那么VA_X-2366绝对值得你拥有。
《VA插件FOR VS2010:提升C++编程体验》 Visual Assist X(简称VA X)是一款专为Visual Studio 2010设计的强大插件,它为C++开发人员提供了类似Eclipse中Java代码编辑的智能提示功能,极大地提升了编程效率。通过在...
【标题】"va_x piaoyun" 指的可能是某个特定的软件或系统组件,结合描述中的重复性,可以推测这可能是一款名为 "va_x piaoyun" 的应用或者服务。在IT领域中,这样的命名通常代表了产品或项目的内部代号或者版本标识...
VA_X官方下载链接:http://www.wholetomato.com/downloads/default.asp VA_X历史版本下载:http://support.wholetomato.com/default.asp?W422 2. 运行Visual Assist X 通用破解补丁程序,点击安装,重新启动VS输入...
对于日常使用,如文档编辑、网络浏览、视频播放等,这款显卡应该能够胜任。 5. 兼容性与升级: 考虑到NEC VA12H是老款笔记本,升级显卡可能受限于主板插槽、电源供应以及散热设计。若想提升图形性能,可尝试更换更...
【VA_X_Setup2212 vs2017 可用】 在IT领域,"VA_X_Setup2212 vs2017可用"这个标题涉及到的是一个软件安装程序,表明该程序与Visual Studio 2017兼容。VA_X可能是软件的一个组件或者插件,而Setup2212则是该组件或...
C语言中的va函数,也就是可变参数函数(variable argument function),允许函数接收不定数量的参数,这种机制为函数调用提供了极大的灵活性。在C/C++标准库中,printf()和scanf()系列函数就是典型的可变参数函数,...
标题中的"VA.X支持va2017 亲测可用"指的是Visual Assist X(简称VA.X)这款插件已经经过验证,可以与Visual Studio 2017版本兼容。Visual Assist X是Whiztler Software公司开发的一款强大的Visual Studio集成开发...
VA_X_Setup2210 + VA_X.dll破解补丁,支持2008-2017均可用。 在用户路径下找到VA_X.dll文件,使用下载的VA_X.dll文件替换即可。 在VisualStudio这个文件夹里面有与你当前安装的VS相关的文件夹,我只装了VS2015版本...
《Visual Assist X for VS2019:提升...无论你是初学者还是经验丰富的专业人士,VA X都能成为你编程旅程中不可或缺的伙伴。通过熟练掌握和运用这款工具,你将在C++编程的世界里游刃有余,享受编程带来的乐趣和成就感。
此外,他还强调这是为了分享给有需要的人,体现了开源和共享的精神。 "标签"部分列出了"VA插件"、"小番笳"、"VS插件"、"VA_X.dll"和"VA插件安装方法",这些标签揭示了以下几个关键信息: 1. "VA_X.dll":这是VA...
《支持VS2019的VA_X_Setup2341_2和谐版:全面...总的来说,VA_X_Setup2341_2和谐版为VS2019用户带来了更优质的编程体验,无论是新手还是经验丰富的开发者,都能从中受益。只需简单安装,即可解锁更多高效开发的可能性。
"va_list原理解释" va_list是C语言中解决变参问题的一组宏,在头文件下。va_list的用法可以分为四步: 1. 首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针。 2. 然后用VA_START宏初始化变量刚定义...
无论是经验丰富的系统管理员,还是初入职场的新手,熟练掌握VA01的功能与流程,都是实现业务高效运作的关键。本文将详细介绍如何使用SAP中的VA01创建客户订单,并且解析其中的关键知识点和操作要点。 VA01事务代码...
【VC助手 VA_X2333 VS2019可用】是一个专为Visual Studio 2019设计的辅助工具,旨在提升开发者的编程效率和软件性能。此工具的使用表明,它能够与Visual Studio 2019无缝集成,无需进行复杂的配置,只需在安装完成后...
va
9. **代码审查**:VA支持代码审查功能,便于团队成员之间分享和讨论代码,提高代码审查的效率。 10. **版本控制集成**:与常见的版本控制系统如Git、SVN等无缝集成,使版本控制操作更加方便。 在安装和使用VA的...