Web爬网简介:使用Java解析Craiglist

Web抓取或抓取是通过下载并解析HTML代码以提取所需数据来从第三方网站获取数据的事实。

由于每个网站都不提供干净的API或根本不提供API,因此在提取网站信息时,网络抓取可能是唯一的解决方案。

许多公司都使用它来获取有关竞争对手价格,新闻汇总和大量电子邮件收集的知识……

几乎所有内容都可以从HTML中提取,唯一“难以提取”的信息是图像或其他媒体内部。

在这篇文章中,我们将看到基本的技术,以便在Java中获取和解析数据。

本文摘自我的新书《 Java Web Scraping Handbook》 这本书将教您网络抓取的崇高艺术。 从解析HTML到打破验证码,处理Javascript繁重的网站等等。

先决条件

  • 基本的Java知识
  • 基本XPath

您将需要带有HtmlUnit的 Java 8

< dependency > 
   < groupId > net.sourceforge.htmlunit </ groupId
   < artifactId > htmlunit </ artifactId > 
   < version > 2.19 </ version > 
</ dependency >

如果您使用的是Eclipse,建议您在详细信息窗格中(当您单击“变量”选项卡时)配置最大长度,以便您可以看到当前页面的整个HTML。

让我们刮一下CraigList

对于第一个示例,我们将从CraigList中获取项目,因为它们似乎不提供API,无法收集名称,价格和图像并将其导出为JSON。

首先,让我们看一下在CraigList上搜索项目时会发生什么。 打开Chrome Dev工具,然后点击“网络”标签:

搜索网址为: https://newyork.craigslist.org/search/moa?is_paid=all&search_distance_type=mi&query=iphone+6s : https://newyork.craigslist.org/search/moa?is_paid=all&search_distance_type=mi&query=iphone+6s

您还可以使用https://newyork.craigslist.org/search/sss?sort=rel&query=iphone+6s

现在您可以打开自己喜欢的IDE了,该进行编码了。 HtmlUnit需要WebClient发出请求。 有很多选项(代理设置,浏览器,已启用重定向...)

我们将禁用Javascript,因为我们的示例不需要使用Javascript,并且禁用Javascript可加快页面加载速度:

String searchQuery = "Iphone 6s" ;

WebClient client = new WebClient();  
client.getOptions().setCssEnabled( false );  
client.getOptions().setJavaScriptEnabled( false );  
try {  
  String searchUrl = "https://newyork.craigslist.org/search/sss?sort=rel&query=" 
    + URLEncoder.encode(searchQuery, "UTF-8" );
  HtmlPage page = client.getPage(searchUrl);
} catch (Exception e){
  e.printStackTrace();
}

HtmlPage对象将包含HTML代码,您可以使用asXml()方法访问它。

现在,我们将获取标题,图像和价格。 我们需要检查项目的DOM结构:

使用HtmlUnit,您可以选择几个选项来选择html标签:

  • getHtmlElementById(String id)
  • getFirstByXPath(String Xpath) - getByXPath(String XPath)返回列表的getFirstByXPath(String Xpath) - getByXPath(String XPath)
  • 还有很多,rtfm!

由于没有可用的ID,我们必须制作一个Xpath表达式来选择所需的标签。

XPath是一种查询语言,用于选择XML节点(在本例中为HTML)。

首先,我们将选择所有具有类`result-info`<p>标签。

然后,我们将遍历此列表,并为每个项目选择名称,价格和url,然后打印出来。

List<HtmlElement> items = (List<HtmlElement>) page.getByXPath( "//li[@class='result-row']" ) ;
if (items.isEmpty()){
  System.out.println( "No items found !" );
} else {
  for (HtmlElement htmlItem : items){
    HtmlAnchor itemAnchor = ((HtmlAnchor) htmlItem.getFirstByXPath( ".//p[@class='result-info']/a" ));
    HtmlElement spanPrice = ((HtmlElement) htmlItem.getFirstByXPath( ".//a/span[@class='result-price']" )) ;

    // It is possible that an item doesn't have any price, we set the price to 0.0 in this case
    String itemPrice = spanPrice == null ? "0.0" : spanPrice.asText() ;

    System.out.println( String.format( "Name : %s Url : %s Price : %s" , itemName, itemPrice, itemUrl));
  }
}

然后,我们将不只是打印结果,而是使用Jackson库将其放入JSON中,以JSON格式映射项目。

首先,我们需要一个POJO(普通的旧Java对象)来表示Items

Item.java

public class Item  {  
    private String title ; 
    private BigDecimal price ;
    private String url ;
//getters and setters
}

然后将其添加到您的pom.xml

< dependency > 
  < groupId > com.fasterxml.jackson.core </ groupId >
  < artifactId > jackson-databind </ artifactId > 
  < version > 2.7.0 </ version > 
</ dependency >

现在,我们要做的就是创建一个Item,设置其属性,并将其转换为JSON字符串(或文件…),然后稍微修改一下先前的代码:

for (HtmlElement htmlItem : items){
	HtmlAnchor itemAnchor = ((HtmlAnchor) htmlItem.getFirstByXPath( ".//p[@class='result-info']/a" ));
	HtmlElement spanPrice = ((HtmlElement) htmlItem.getFirstByXPath( ".//a/span[@class='result-price']" )) ;

	// It is possible that an item doesn't have any price, we set the price to 0.0 in this case
	String itemPrice = spanPrice == null ? "0.0" : spanPrice.asText() ;

	Item item = new Item();
	item.setTitle(itemAnchor.asText());
	item.setUrl( baseUrl + itemAnchor.getHrefAttribute());

	item.setPrice( new BigDecimal(itemPrice.replace( "$" , "" )));


	ObjectMapper mapper = new ObjectMapper();
	String jsonString = mapper.writeValueAsString(item) ;

	System.out.println(jsonString);
}

走得更远

这个例子并不完美,有很多地方可以改进:

  • 多城市搜寻
  • 处理分页
  • 多条件搜索

您可以在此Github存储库中找到代码

希望您喜欢这篇文章,并随时在评论中给我反馈。

本文摘自我的新书: Java Web Scraping Handbook 这本书将教您网络抓取的崇高艺术。 从解析HTML到打破验证码,处理Javascript繁重的网站等等。

From: https://hackernoon.com/introduction-to-web-scraping-with-java-3d8a8d0f250b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; public class GetNetHtml { public static String createhttpClient(String url, String param) { HttpClient client = new HttpClient(); String response = null; String keyword = null; PostMethod postMethod = new PostMethod(url); // try { // 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); // 以上部分是带参数抓取,我自己把它注销了.大家可以把注销消掉研究下 try { 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(); } return response; } // 第二种方法 // 这种方法是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"); try { 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(); } /*部分删节,请下载细看!!*/ public static void main(String[] args) { String url = "http://www.liuzm.com"; String keyword = "刘志猛博客"; GetNetHtml p = new GetNetHtml(); String response = p.createhttpClient(url, keyword); // 第一种方法 // p.getPageContent(url, "post", 100500);//第二种方法 } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值