-
2020-07-12 16:23:36
爬取京东商品案例
需求分析
一、需求
抓取京东商城的数据,把商品数据保存到数据库。二、功能分析
- 使用HttpClient发送一个get请求,请求搜索url,得到商品列表
- 使用jsoup解析搜索结果页面。
- 把商品信息封装一个对象中。
- 把商品数据保存到数据库。
三、京东页面分析
当在京东的搜索框输入手机时,此时的url为https://search.jd.com/Search?keyword=手机&wq=手机&page=1&s=1&click=1
当进行翻页操作,发现page值为1,3,5,7…进一步分析发现,京东商品每一页展示两页数据,当看完一页数据后,拉到底部,会显示第二页数据,当看完第二页数据,才会进行翻页操作,此时真正进入第二页。
问题:京东商城每次只展示30条数据,后30条数据(每页的第二页)是ajax动态加载的,使用HttpClient解决非常麻烦,此处不进行爬取后30条数据。
爬取页数:取10页数据。
爬取的信息:商品标题,价格,图片,skuid,spuid,商品详情地址等
四、数据库表创建
保存到数据库:创建一个数据库。需要的字段都是商品列表中可以解析出来的字段。
CREATE TABLE `jd_item` ( `id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键id', `spu` bigint(15) DEFAULT NULL COMMENT '商品集合id', `sku` bigint(15) DEFAULT NULL COMMENT '商品最小品类单元id', `title` varchar(1000) DEFAULT NULL COMMENT '商品标题', `price` float(10,0) DEFAULT NULL COMMENT '商品价格', `pic` varchar(200) DEFAULT NULL COMMENT '商品图片', `url` varchar(1500) DEFAULT NULL COMMENT '商品详情地址', `created` datetime DEFAULT NULL COMMENT '创建时间', `updated` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`), KEY `sku` (`sku`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=217 DEFAULT CHARSET=utf8 COMMENT='京东商品';
代码实现
编写爬虫的业务逻辑
1、使用工具类创建一个HttpClient对象。
2、使用HttpClient发送请求,请求就是搜索的url+页码
3、接收服务端响应html
4、使用Jsoup解析html
5、把解析的商品数据封装成Item对象
6、使用dao把商品写入数据库。
7、需要翻页。注意:图片也是一个http请求,需要再次发起请求爬取图片,然后存储到本地
@Component public class Crawler { @Autowired private ItemDao itemDao; private String startUrl = "https://search.jd.com/Search?keyword=手机&wq=手机&s=1&click=1&page="; /** * 爬取页面 */ public void doCrawler() { try { //1、使用工具类创建一个HttpClient对象。 CloseableHttpClient httpClient = HttpsUtils.getHttpClient(); for (int i = 0; i < 10; i++) { //2、使用HttpClient发送请求,请求就是搜索的url+页码 HttpGet get = new HttpGet(startUrl + (i * 2 + 1)); get.addHeader("User-Agent", " Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0"); CloseableHttpResponse response = httpClient.execute(get); //3、接收服务端响应html HttpEntity entity = response.getEntity(); String html = EntityUtils.toString(entity, "utf-8"); //4、使用Jsoup解析html parseHtml(html); //5、把解析的商品数据封装成Item对象 //6、使用dao把商品写入数据库。 //7、需要翻页。 } } catch (Exception e) { e.printStackTrace(); } } /** * 页面解析 * @param html */ private void parseHtml(String html) throws Exception { //4、使用Jsoup解析html Document document = Jsoup.parse(html); //解析商品列表 Elements elements = document.select("li.gl-item"); for (Element element : elements) { //解析节点中的商品数据 //spu String spu = element.attr("data-spu"); //sku String sku = element.attr("data-sku"); //title String title = element.select("div.p-name em").text(); //price String price = element.select("div.p-price i").text(); //图片 String imgUrl = element.select("div.p-img img").attr("src"); String imageName = downloadImage(imgUrl); //商品的url String itemUrl = element.select("div.p-img > a").attr("href"); //5、把解析的商品数据封装成Item对象 Item item = new Item(); item.setSpu(Long.parseLong(spu)); item.setSku(Long.parseLong(sku)); item.setTitle(title); if (StringUtils.isNotBlank(price)) { item.setPrice(Float.parseFloat(price)); } item.setPic(imageName); item.setUrl(itemUrl); item.setCreated(new Date()); item.setUpdated(new Date()); //6、使用dao把商品写入数据库。 itemDao.save(item); } } /** * 爬取图片 * @param imageUrl * @return */ private String downloadImage(String imageUrl) throws Exception { //创建一个HttpClient对象 CloseableHttpClient httpClient = HttpsUtils.getHttpClient(); //创建一个HttpGet对象 HttpGet get = new HttpGet("https:" + imageUrl); get.addHeader("User-Agent", " Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0"); //发送请求 CloseableHttpResponse response = httpClient.execute(get); //接收服务端响应的内容。 HttpEntity entity = response.getEntity(); //需要截取扩展名 String extName = imageUrl.substring(imageUrl.lastIndexOf(".")); //需要生成文件名。可以使用uuid生成文件名。 String fileName = UUID.randomUUID() + extName; //D:\temp\term331\images //创建一个文件输出流,把文件保存到磁盘 FileOutputStream outputStream = new FileOutputStream("D:\\temp\\images\\" + fileName); //接收流,把内容保存到磁盘。 entity.writeTo(outputStream); //关闭流 outputStream.close(); //关闭Response对象 response.close(); return fileName; } }
开启新线程可以让爬取在后台进行,而不是页面一直在转
@RestController public class CrawlerController { @Autowired private Crawler crawler; @RequestMapping("/start") public String startCrawler() { new Thread(new Runnable() { @Override public void run() { System.out.println("新线程已经启动。。。。。"); crawler.doCrawler(); } }).start(); return "OK"; } }
更多相关内容 -
java爬虫 京东商品页 简单案例
2016-04-30 13:41:26java爬虫 HttpClient HtmlCleaner Xpath mysql 京东HttpClient + htmlcleaner + xpath + MySQL Java语言要爬的数据
数据库表结构
数据库建表语句
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `spider` -- ---------------------------- DROP TABLE IF EXISTS `spider`; CREATE TABLE `spider` ( `id` int(10) NOT NULL AUTO_INCREMENT, `goods_id` varchar(20) DEFAULT NULL, `data_url` varchar(300) DEFAULT NULL, `pic_url` varchar(300) DEFAULT NULL, `title` varchar(300) DEFAULT NULL, `price` varchar(10) DEFAULT NULL, `param` text, `current_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
项目的包结构
pom.xml 文件中的jar包依赖
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.4</version> </dependency> <dependency> <groupId>net.sourceforge.htmlcleaner</groupId> <artifactId>htmlcleaner</artifactId> <version>2.16</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20160212</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version> </dependency> </dependencies>
编写实体类
import java.util.HashMap; import java.util.Map; /** * 页面实体类 * 保存页面信息 */ public class Page { private String goodId;// 商品ID private String goodName;//商品名称 private String dataUrl;//商品URL地址 private String picUrl;//商品图片URL地址 private String price;//价格 private Map<String, String> param = new HashMap<String, String>();//商品参数规格 private String content;//页面原始源代码内容 public String getGoodId() { return goodId; } public void setGoodId(String goodId) { this.goodId = goodId; } public String getGoodName() { return goodName; } public void setGoodName(String goodName) { this.goodName = goodName; } public String getDataUrl() { return dataUrl; } public void setDataUrl(String dataUrl) { this.dataUrl = dataUrl; } public Map<String, String> getParam() { return param; } public void setParam(String key,String value) { this.param.put(key, value); } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getPicUrl() { return picUrl; } public void setPicUrl(String picUrl) { this.picUrl = picUrl; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } }
spider类
import cn.crxy.maven.Spider.domain.Page; import cn.crxy.maven.Spider.download.Downloadable; import cn.crxy.maven.Spider.process.Processable; import cn.crxy.maven.Spider.store.Storeable; public class Spider { private Downloadable downloadable; private Processable processable; private Storeable storeable; //下载页面源代码 public Page download(String url){ return downloadable.download(url); } //解析页面源代码 public void process(Page page){ processable.process(page); } //将解析后的数据保存到数据库 public void store(Page page){ storeable.store(page); } public Downloadable getDownloadable() { return downloadable; } public void setDownloadable(Downloadable downloadable) { this.downloadable = downloadable; } public Processable getProcessable() { return processable; } public void setProcessable(Processable processable) { this.processable = processable; } public Storeable getStoreable() { return storeable; } public void setStoreable(Storeable storeable) { this.storeable = storeable; } }
Downloadable接口类
import cn.crxy.maven.Spider.domain.Page; public interface Downloadable { Page download(String url); }
DownloadImpl实现类
import cn.crxy.maven.Spider.domain.Page; import cn.crxy.maven.Spider.utils.PageUtil; public class DownloadImpl implements Downloadable { public Page download(String url) { Page page = new Page(); String content=PageUtil.getContent(url);//根据url得到内容 page.setContent(content); page.setDataUrl(url); return page; } }
PageUtil页面工具类
import java.io.IOException; import org.apache.http.HttpEntity; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; /** * 根据URL获取url对应的内容 */ public class PageUtil { public static String getContent(String url){ HttpClientBuilder custom = HttpClients.custom();//创建httpclient //通过构建器构建一个httpclient对象,可以认为是获取到一个浏览器对象 CloseableHttpClient build = custom.build(); //把url封装到get请求中 HttpGet httpGet = new HttpGet(url); String content = null; try { //使用client执行get请求,获取请求的结果,请求的结果被封装到response中 CloseableHttpResponse response = build.execute(httpGet); //表示获取返回的内容实体对象 HttpEntity entity = response.getEntity(); //解析实体中页面的内容,返回字符串形式 content = EntityUtils.toString(entity); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return content; } }
Processable.java
import cn.crxy.maven.Spider.domain.Page; public interface Processable { void process(Page page); }
ProcessImpl.java
import java.util.regex.Matcher; import java.util.regex.Pattern; import org.htmlcleaner.HtmlCleaner; import org.htmlcleaner.TagNode; import org.htmlcleaner.XPatherException; import org.json.JSONArray; import org.json.JSONObject; import cn.crxy.maven.Spider.domain.Page; import cn.crxy.maven.Spider.utils.HtmlUtil; import cn.crxy.maven.Spider.utils.PageUtil; public class ProcessImpl implements Processable { public void process(Page page) { HtmlCleaner htmlCleaner = new HtmlCleaner(); TagNode rootNode = htmlCleaner.clean(page.getContent()); try { String goodName = HtmlUtil.getText(rootNode, "//*[@id='name']/h1");// 得到商品名称 page.setGoodName(goodName); String picUrl = HtmlUtil.getAttributeByName(rootNode, "//*[@id='spec-n1']/img","src");// 获取商品图片url page.setPicUrl("http:"+picUrl); // 获取商品号 String url = page.getDataUrl(); Pattern compile = Pattern.compile("http://item.jd.com/([0-9]+).html"); Matcher matcher = compile.matcher(url); String goodid = null; if (matcher.find()) { goodid = matcher.group(1); page.setGoodId(goodid); } // 获取商品价格 // 得到价格的json格式[{"id":"J_1593512","p":"17988.00","m":"17989.00"}] String pricejson = PageUtil .getContent("http://p.3.cn/prices/get?skuid=J_" + goodid); JSONArray jsonArray = new JSONArray(pricejson); JSONObject jsonObject = jsonArray.getJSONObject(0); String price = jsonObject.getString("p"); page.setPrice(price); // 获取规格参数 // *[@id="product-detail-2"] // *[@id="product-detail-2"]/table/tbody/tr[1]/th Object[] evaluateXPath = rootNode .evaluateXPath("//*[@id='product-detail-2']/table/tbody/tr"); JSONArray jsonArray2 = new JSONArray(); if(evaluateXPath != null && evaluateXPath.length > 0){ for(Object object : evaluateXPath){ TagNode tagnode = (TagNode) object; if(!"".equals(tagnode.getText().toString().trim())){//有数据 Object[] evaluateXPath2 = tagnode.evaluateXPath("/th"); JSONObject jsonObject2 = new JSONObject(); if(evaluateXPath2.length>0){ TagNode tagNode2 = (TagNode) evaluateXPath2[0]; jsonObject2.put("name", tagNode2.getText().toString()); jsonObject2.put("value", ""); }else { Object[] evaluateXPath3 = tagnode.evaluateXPath("/td"); TagNode tagNode1 = (TagNode) evaluateXPath3[0]; TagNode tagNode2 = (TagNode) evaluateXPath3[1]; jsonObject2.put("name", tagNode1.getText().toString()); jsonObject2.put("value", tagNode2.getText().toString()); } jsonArray2.put(jsonObject2); } } } page.setParam("spec",jsonArray2.toString()); } catch (XPatherException e) { e.printStackTrace(); } } }
ProcessImpl.java代码中的几个注意点:
获取商品名称、图片URL的xpath路径
在京东商品页面获取商品价格的方式
得到如下的连接地址:
对连接进行处理后得到如下结果http://p.3.cn/prices/get?type=1&area=1_72_4137&pdtk=&pduid=1112434089&pdpin=&pdbp=0&skuid=J_1593512&callback=cnp
商品参数规格的Xpath
Storeable.java
package cn.crxy.maven.Spider.store; import cn.crxy.maven.Spider.domain.Page; public interface Storeable { void store(Page page); }
StoreImple.java
package cn.crxy.maven.Spider.store; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import cn.crxy.maven.Spider.domain.Page; import cn.crxy.maven.Spider.utils.MyDBUtils; public class StoreImpl implements Storeable { public void store(Page page) { String dataUrl = page.getDataUrl(); String goodid = page.getGoodId(); String goodname = page.getGoodName(); String picUrl = page.getPicUrl(); String price = page.getPrice(); Map<String, String> values = page.getParam(); String param = values.get("spec"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String currtime = sdf.format(new Date()); MyDBUtils.update(MyDBUtils.INSERT_LOG, goodid,dataUrl,picUrl,goodname,price,param,currtime); } }
MyDBUtils.java
package cn.crxy.maven.Spider.utils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.apache.commons.dbutils.BasicRowProcessor; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.ArrayListHandler; public class MyDBUtils { private static String className = "com.mysql.jdbc.Driver"; private static String url = "jdbc:mysql://localhost:3306/spider?" + "useUnicode=true&characterEncoding=utf-8"; private static String user = "root"; private static String password = "1234"; private static QueryRunner queryRunner = new QueryRunner(); public static final String INSERT_LOG = "INSERT INTO SPIDER(good_id," + "data_url,pic_url,good_name,price,param,`current_time`) " + "VALUES(?,?,?,?,?,?,?)"; // 拒绝new一个实例 private MyDBUtils() { }; static {// 调用该类时既注册驱动 try { Class.forName(className); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(); } } //查询 public static List<String> executeQuerySql(String sql) { List<String> result = new ArrayList<String>(); try { List<Object[]> requstList = queryRunner.query(getConnection(), sql, new ArrayListHandler(new BasicRowProcessor() { @Override public <Object> List<Object> toBeanList(ResultSet rs, Class<Object> type) throws SQLException { return super.toBeanList(rs, type); } })); for (Object[] objects : requstList) { result.add(objects[0].toString()); } } catch (SQLException e) { e.printStackTrace(); } return result; } //这个方法可以执行一些更新或者新增的sql语句或者删除 public static void update(String sql, Object... params) { try { Connection connection = getConnection(); queryRunner.update(connection, sql, params); connection.close(); } catch (SQLException e) { e.printStackTrace(); } } // 获取连接 private static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); } }
HtmlUtils.javaimport org.htmlcleaner.TagNode; import org.htmlcleaner.XPatherException; public class HtmlUtils { /** * 根据xpath获取对应标签的内容 * @param tagNode * @param xpath * @return */ public static String getText(TagNode tagNode,String xpath){ String content = null; Object[] evaluateXPath; try { evaluateXPath = tagNode.evaluateXPath(xpath); if(evaluateXPath!=null && evaluateXPath.length>0){ TagNode node = (TagNode)evaluateXPath[0]; content = node.getText().toString(); } } catch (XPatherException e) { e.printStackTrace(); } return content; } /** * 获取对应标签中指定属性的值 * @param tagNode * @param xpath * @param attr * @return */ public static String getAttributeByName(TagNode tagNode,String xpath,String attr){ String content = null; Object[] evaluateXPath; try { evaluateXPath = tagNode.evaluateXPath(xpath); if(evaluateXPath!=null && evaluateXPath.length>0){ TagNode node = (TagNode)evaluateXPath[0]; content = node.getAttributeByName(attr); } } catch (XPatherException e) { e.printStackTrace(); } return content; } }
在src/test/java文件夹下面的包中新建test类TestSpider.javapackage cn.crxy.maven.Spider; import org.junit.Test; import cn.crxy.maven.Spider.domain.Page; import cn.crxy.maven.Spider.download.DownloadImpl; import cn.crxy.maven.Spider.process.ProcessImpl; import cn.crxy.maven.Spider.store.StoreImpl; public class TestSpider { @Test public void test1() throws Exception { Spider spider = new Spider(); //给接口注入实现类 spider.setDownloadable(new DownloadImpl()); spider.setProcessable(new ProcessImpl()); spider.setStoreable(new StoreImpl()); String url = "http://item.jd.com/1593512.html"; Page page = spider.download(url); spider.process(page); spider.store(page); } }
运行test测试方法,在数据库中插入了数据
-
Java爬虫爬取京东商城
2022-02-23 23:23:00旨在通过使用java爬虫,提取网络中的各种商品信息,并收集的商品信息建立统一数据模型存储数据,通过数据模型描述商品的基本属性。如spu,sku,商品描述,价格等信息,同时需要剔除非必要信息,做到精准分析。根据所...一、任务:
旨在通过使用java爬虫,提取网络中的各种商品信息,并收集的商品信息建立统一数据模型存储数据,通过数据模型描述商品的基本属性。如spu,sku,商品描述,价格等信息,同时需要剔除非必要信息,做到精准分析。根据所获取的信息提供商品展示页面,通过搜索,得到商品数据信息。抓取商品数据,建立统一数据模型,模型的可扩展性,商品数据展示。
目的:该项目有利于简单理解java的爬虫过程,spring boot简单的项目调试,调用,映射方式,数据库连接,帮助理解的前后端交互原理。
二、类及数据的设计
2.1项目的开发环境
2.2系统功能结构设计
该程序主要通过调用webmagic使用爬虫功能爬取数据,建立数据模型,利用MySQL存储数据。查询调用数据库内容,模型的可扩展性,通过html/css提供web页面展示。
2.2.1数据爬取,数据模型建立
WebMagic:
WebMagic的结构分为Downloader、PageProcessor、Scheduler、Pipeline四大组件,并由Spider将它们彼此组织起来。
1)Downloader:负责从互联网上下载页面,以便后续处理。WebMagic默认使用了Apache HttpClient作为下载工具。
2)PageProcessor:负责解析页面,抽取有用信息,以及发现新的链接。WebMagic使用Jsoup作为HTML解析工具,并基于其开发了解析XPath的工具Xsoup。在这四个组件中,PageProcessor对于每个站点每个页面都不一样,是需要使用者定制的部分。
3)Scheduler:负责管理待抓取的URL,以及一些去重的工作。WebMagic默认提供了JDK的内存队列来管理URL,并用集合来进行去重。也支持使用Redis进行分布式管理。除非项目有一些特殊的分布式需求,否则无需自己定制Scheduler。
4)Pipeline:负责抽取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供了“输出到控制台”和“保存到文件”两种结果处理方案。Pipeline定义了结果保存的方式,如果你要保存到指定数据库,则需要编写对应的Pipeline。对于一类需求一般只需编写一个Pipeline。
Selenium:
Selenium是一个Web的自动化测试工具,可以根据我们的指令,使用代码控制浏览器,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生,支持主流的浏览器
该程序使用Downloader、PageProcessor、Pipeline,Spider组件进行爬虫,建立数据模型。通过selenium对谷歌无头浏览器进行自动化操作。
1、定时任务
在springboot工程中使用定时器。在工程中创建一个普通的类,添加注解@Component,
在定义方法上使用@Scheduled注解标注,配置定期执行时间,在spring boot工程的引导类上添加@EnableScheduling注解。
2、设置代理
使用代理服务器发起请求,防止反爬策略封ip
代理服务器流程:
爬虫服务器 -> 代理服务器 -> 目标服务器
目标服务器 -> 代理服务器 -> 爬虫服务器 ->解析数据
可用的免费代理:
http://www.xiladaili.com/gaoni/
3、使用selenium+无头浏览器抓取数据
通过Maven添加Selenium依赖。Selenium是一个前端的测试框架,通过Selenium使用代码控制浏览器。
无头浏览器:没有界面的浏览器,解析js。得到一些默认不到的数据。用于各类测试场景,在任何给定页面上可采取的频繁重复的操作,反复测试。
4、使用浏览器渲染,抓取京东商城的数据并保存
1)PageProcess解析html
1. 判断是列表页面还是详细页面
2. 如果是列表页面
a、解析列表中的商品数据,去sku和spu,封装成一个对象,传递给pipeline
b、解析商品的链接地址,把地址添加到访问队列中
c、翻页处理,设置固定url:Enterprise Cybersecurity Solutions, Services & Training | Proofpoint US 添加一个附件:当前请求的url
3. 如果是详细页面
a、解析商品的详细信息
b、把详细信息封装成一个商品对象
c、传递给pipeline
2)Downloader下载页面
1. 抓取列表页面
a、访问url
b、页面滚动到最下方
c、从浏览器中取html
d、需要把结构封装成Page对象
2. 如果是详情页面
a、直接访问url
b、取html,封装成Page,返回
3. 如果是翻页处理
a、从Request对象中取附件,翻页之前的url
b、访问url
c、点击翻页按钮,翻到第二页
d、让页面滚到最下方,加载30条数据
e、把去浏览器渲染的html结果封装成Page对象返回
3)Pipeline保存到数据库
创建数据库表,创建对应的属性
5、模型的可扩展性
基于springboot的控制反转,类与类之间没有很强的耦合性,具有很好的“特性:“高内聚、低耦合”实例化的操作交给Spring 的bean工厂,通过xml配置文件去记录。所以模型具有很强的可扩展性。只需在Item中添加属性,并添加对应的浏览器操作。
2.2.2 SpringBoot+Ajax+MyBatis查询操作数据库
开发顺序
后端SpringBoot+MyBatis, 前端Ajax+jQuery+CSS+HTML,通过爬虫操作得到数据,根据数据对于后端接口数据设计和使用,前端数据请求和响应填充界面的过程,数据库采用MySQL 8.0.26,用于学习掌握前后端开发的关键技术和开发架构。
随着 Spring Boot 越来越流行,MyBatis 也开发了一套基于 Spring Boot 模式的 starter:mybatis-spring-boot-starter。
entity层:存放的是实体类,属性值与数据库值保持一致,实现 setter 和 getter 方法。
dao层:即 mapper层,对数据库进行持久化操作,他的方法使针对数据库操作的,基本上用的就是增删改查。作为接口,只有方法名,具体实现在mapper.xml中实现。
service层:业务层,存放业务逻辑处理,不直接对数据库进行操作,有接口和接口实现类,提供 controller 层调用方法。
controller层:控制层,导入 service层,调用你service方法,controller通过接受前端传来的参数进行业务操作,在返回一个制定的路径或数据表。
选择ajax原因是基于爬虫操作数据量大,变化多,AJAX能提供在无需重新加载整个网页的情况下,能够更新部分网页的技术。AJAX 是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
而选择MyBatis,因为MyBatis可以使用简单的XML或注释进行配置,并将图元,映射接口和 POJO映射到数据库记录。消除了大部分JDBC代码以及参数的手动设置和结果检索。同时基于MyBatis灵活特性,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,更加为程序的可拓展性提供基础。
三、部分代码
3.1爬虫部分
@Override public void process(Page page) { String level = page.getRequest().getExtra("level").toString(); switch (level){ case "list": parseList(page); break; case "detail": praseDetail(page); break; } /** * 解析详情页 * * @param page */ private void praseDetail(Page page) { Html html = page.getHtml(); String title = html.$("div.master .p-name").xpath("///allText()").get(); String priceStr = html.$("div.summary-price-wrap .p-price span.price").xpath("///allText()").get(); String pic = "https:"+html.$("#spec-img").xpath("///@src").get(); String url = "https:"+html.$("div.master .p-name a").xpath("///@href").get(); String sku = html.$("a.notice.J-notify-sale").xpath("///@data-sku").get(); Item item = new Item(); item.setTitle(title); item.setPic(pic); item.setPrice(Float.valueOf(priceStr)); item.setUrl(url); item.setUpdated(new Date()); item.setSku(StringUtils.isNotBlank(sku)?Long.valueOf(sku) : null); // 单条数据塞入 page.putField("item", item); } /** * 解析列表页 * @param page */ private void parseList(Page page) { Html html = page.getHtml(); // 这里拿到sku 和 spu 并交给pipeline List<Selectable> nodes = html.$("ul.gl-warp.clearfix > li").nodes(); List<Item> itemList = new ArrayList<>(); for (Selectable node : nodes) { // 拿到sku和spu String sku = node.$("li").xpath("///@data-sku").get(); String spu = node.$("li").xpath("///@data-spu").get(); String href = "https:" + node.$("div.p-img a").xpath("///@href").get(); Item item = new Item(); item.setSku(Long.valueOf(sku)); item.setSpu(StringUtils.isNotBlank(spu) ? Long.valueOf(spu) : 0); item.setCreated(new Date()); itemList.add(item); // 同时还需要把链接加到详情页 加到队列 Request request = new Request(href); request.putExtra("level", "detail"); request.putExtra("pageNum", page.getRequest().getExtra("pageNum")); request.putExtra("detailUrl", href); page.addTargetRequest(request); } // 以集合的方式存入 page.putField("itemList", itemList); // 同时还要去做分页 String pageNum = page.getRequest().getExtra("pageNum").toString(); if ("1".equals(pageNum)){ Request request = new Request("https://nextpage.com"); request.putExtra("level", "page"); // 标识去分页 request.putExtra("pageNum", (Integer.valueOf(pageNum) + 1) + "");// 页码要+1 接下来要的是第二页 // 添加到队列 page.addTargetRequest(request); }
3.2 spring boot查询操作数据库
Control控制层: @RestController//返回rest服务类型的数据格式 @RequestMapping("/Jd")//数据接口controller怎么被调用 public class ItemController { //调用一些方法得到返回值,把服务层作为对象 @Autowired//自动注入,生成实例 private ItemService itemService;//好封装 @GetMapping("/getJd")//路径如果是Jd下的getJd,会获得前端传来的参数‘id',获得值,把id值传到findById方法中 public String getItem(@Param("id")Integer id){ Item item = itemService.findById(id); return item.getTitle(); } @GetMapping("/getId") // 通过title// 获取id public Integer getId(@Param("Message") String title){ Item item = itemService.findByTitle(title); return item.getId(); } @GetMapping("/getOne") // 通过title// 获取id,一条数据记录 public Item getAll(@Param("id") Integer id){ Item item = itemService.findById(id); return item; } @GetMapping("/getJson") // 通过title获取id public String getJson(@Param("id") Integer id) { Item item = itemService.findById(id); Gson gson = new Gson(); return gson.toJson(item); } @GetMapping("/getAll") // 通过title获取id,获得多条数据 public List<Item> getAll(){ List<Item> list = itemService.findItemAll(); return list; } @GetMapping("/getAllJson") // 通过title获取id public String getAllJson(){ List<Item> list = itemService.findItemAll(); Gson gson = new Gson(); return gson.toJson(list); } }
3.3前端设计
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" type="text/css"href="https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css"> <script type="text/javascript"src="https://cdn.bootcss.com/jquery/1.4.0/jquery.js"></script> <script> $(document).ready(function(){ $("#btn1").click(function(){ test1(); }); $("#btn2").click(function(){ $.test2(); }); }); //data为数组 function test1(){ //alert("Text1: " + $("#test").text()); $.ajax({ url:'/msg/getAllJson',//访问后台接口,用get,后台返回json type:'get', dataType:'json', success:function(data){ $("#tabletest").find('tr').remove(); tr='<td>id</td><td>title</td>' $("#tabletest").append('<tr>'+tr+'</tr>') //方法中传入的参数data为后台获取的数据 for(i in data) //data指的是数组,i为数组的索引 { var tr; tr='<td>'+data[i].id+'</td>'+'<td>'+data[i].title +'</td>' $("#tabletest").append('<tr>'+tr+'</tr>') } } }); } </script> <style type="text/css"> .center{ margin: auto; text-align:center; font-size: 24px; width: 60%; background: lightblue; } </style> </head> <body> <div class="center"> <p id="test">Springboot整合MyBatis通过ajax查询MySQL数据库数据</b></p> <button id="btn1">显示所有数据</button> <button id="btn2">查询</button> <input id="id" name="id" type="text" placeholder="请输入id值"/> <br> <table class="table table-bordered" id='tabletest'> </table> </div> </body> </html>
四、程序运行、测试与分析
4.1程序运行
4.2总结分析
- 在使用java程序应注意jdk版本问题,以及jdk对应的数据库版本。
- 在使用数据库操作时,应注意数据库与idea连接application中的url,username,password格式问题。
- 应注意传入数据文件路径相对绝对路径问题。
- 学习通过debug,逐步了解一个项目的进程,排除错误。
- 在调试程序中,应该带着思考搜索解决方式,逐一排除造成错误的原因。
- 了解各种注释API作用,有助于优化代码。
- 对于繁多的技术,需要从需求出发,合理选择合适,高效,可拓展的技术。
- 通过程序更加深入了解前后端工作方式,更加理解springboot的工作原理。
4.3改进方案
4.3.1对于爬虫:
首先可以通过更高效的框架加快爬虫速度,实现更加灵活的定制化爬取。其次,可以通过优化算法,对于一些爬取失败或数据获取失败的记录进行汇总,在页面反馈成功完整数据,通过网页分析算法过滤主题无关的链接。
交互问题是一个需要解决的问题,爬取会页面涉及到用户信息输入,验证码处理,随着各类花样繁多的验证码的出现,爬虫遇到这种情况会很难处理。
Javascript 解析问题,目前大多数网页属于动态网页,网页中大多数有用的数据都是通过ajax/fetch动态获取后然后再由js填充到网页,单纯的html静态页面中有用的数据很少。让后台脚本去做javascript操作会很麻烦,不仅需要清楚的理解原网页代码逻辑也会让代码显得很臃肿。
ip解析问题,尽管在本程序使用代理ip,但这仍然是爬虫会遇到的最致命问题。网站防火墙会对某个ip在某段时间内请求的次数做限制,如果超过上限则拒绝请求。后台爬取时机器和ip有限,很容易达到上线而导致请求被拒绝。目前主要的应对方案是使用代理,这样一来ip的数量就会多一些,但代理ip依然有限。
4.3.2.前端太丑,过于简陋
-
Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup
2020-10-18 23:05:30下面小编就为大家分享一篇Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 -
Java爬虫技术(二)爬取京东iPhone商品信息并生成Json日志
2021-12-15 11:40:11将页面滑到最底部,因为京东页面若不滑到最下面会导致有些数据加载不出来 ((JavascriptExecutor)webDriver).executeScript("window.scrollTo(0,document.body.scrollHeight)"); 获取源码 String pageSource = ...准备
配置maven环境
下载浏览器驱动,并引入;下载浏览器驱动
前往华为云镜像站下载谷歌浏览器驱动
https://mirrors.huaweicloud.com/home
要下载与自己电脑上谷歌浏览器版本相匹配的;引入pom.xml依赖
<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>3.141.59</version> </dependency> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-api</artifactId> <version>3.141.59</version> </dependency>
开始爬取
目标网址
https://search.jd.com/Search?keyword=iphone%2013&psort=3&wq=iphone%2013&psort=3&pvid=37f665a84459460eb713df08bdcd7799&page=1&s=1&click=0
目标是爬取所有47页的商品的 价格,商品名称,商品描述;第一页网址:
https://search.jd.com/Search?keyword=iphone%2013&psort=3&wq=iphone%2013&psort=3&pvid=37f665a84459460eb713df08bdcd7799&page=1&s=1&click=0
第二页网址:
https://search.jd.com/Search?keyword=iphone%2013&psort=3&wq=iphone%2013&psort=3&pvid=37f665a84459460eb713df08bdcd7799&page=3&s=61&click=0
第三页网址:
https://search.jd.com/Search?keyword=iphone%2013&psort=3&wq=iphone%2013&psort=3&pvid=37f665a84459460eb713df08bdcd7799&page=5&s=121&click=0
经过分析发现规律: page=1 , 3 , 5 为奇数 --2i+1
s =1,60,121 依次加60-- ((i-1)*60)+1主要代码与操作步骤
定义一个浏览器对象
ChromeDriver webDriver = new ChromeDriver();
利用循环爬取45页的数据
for(int i=1;i<45;i++) { webDriver.get("https://search.jd.com/search?keyword=iphone%2013&wq=iphone%2013&cid3=655&psort=3&page="+((2*i)-1)+"&s="+((i-1)*60)+1+"&click=0");
将页面滑到最底部,因为京东页面若不滑到最下面会导致有些数据加载不出来
((JavascriptExecutor)webDriver).executeScript("window.scrollTo(0,document.body.scrollHeight)");
获取源码
String pageSource = webDriver.getPageSource();
选中一个单元获取其路径
#J_goodsList > ul > li:nth-child(13) > div
#J_goodsList > ul > li:nth-child > div
查看价格路径
#J_goodsList > ul > li:nth-child(16) > div > div.p-price > strong > i
在其循环体下
div.p-price > strong > i
同理:店铺名称路径
div.p-shop > span > a
商品描述路径:div.p-name.p-name-type-2 > a > em
还要创建一个product类并建对象:
package com.zygxy.shop; public class Product { private String price; private String shopname; private String shopcontext; public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } public String getShopname() { return shopname; } public void setShopname(String shopname) { this.shopname = shopname; } public String getShopcontext() { return shopcontext; } public void setShopcontext(String shopcontext) { this.shopcontext = shopcontext; } }
全部代码
package com.zygxy.shop; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.chrome.ChromeDriver; import java.io.IOException; import java.util.Properties; @Slf4j public class JD { public static void main(String[] args) throws IOException { Properties properties = new Properties(); properties.load(JD.class.getClassLoader().getResourceAsStream("application.properties")); System.out.println(properties.getProperty("chromedriver")); System.setProperty("webdriver.chrome.driver",properties.getProperty("chromedriver")); ChromeDriver webDriver = new ChromeDriver(); for (int i=1;i<45;i++){ webDriver.get("https://search.jd.com/search?keyword=iphone%2013&psort=3&wq=iphone%2013&psort=3&pvid=aa23e9f58a714e9087f316ab6aa993bd&cid3=655&cid2=653&page="+((2*i)-1)+"&s="+((i-1)*60)+1+"&click=0"); ((JavascriptExecutor) webDriver).executeScript("window.scrollTo(0,document.body.scrollHeight)"); String pageSource = webDriver.getPageSource(); Document parse = Jsoup.parse(pageSource); Elements select = parse.select("#J_goodsList > ul > li > div "); for(Element e : select){ Product product = new Product(); Element price = e.selectFirst(" div.p-price > strong > i"); product .setPrice(price.text()); Element shop_name = e.selectFirst(" div.p-shop > span > a"); product.setShopname(shop_name.text()); Element shopcontext = e.selectFirst(" div.p-name.p-name-type-2 > a > em"); product.setShopcontext(shopcontext.text()); String json = JSONObject.toJSONString(product); log.info(json); } } } }
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>NovelParse</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.13.1</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>3.141.59</version> </dependency> <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-api --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-api</artifactId> <version>3.141.59</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency> <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> <scope>compile</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <!-- 如果已经在Maven的全局配置中,配置了JDK编译的界别,这个插件可以省略 --> <!-- <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> --> <!-- 在mvn:package阶段使用 maven-assembly-plugin可以将当前项目依赖的Jar中的字节码也打包! 默认的打包插件maven-jar-plugin,只会将自己写的代码打包,默认仓库中已经安装了所需的依赖! --> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.zygxy.JD</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
resources配置
application.properties
本地驱动地址
chromedriver =E:\shixun\pachong\src\main\resources\chromedriver.exe
logback.xml 定义了日志的输出地址和格式<?xml version="1.0" encoding="UTF-8"?> <configuration> <property name="LOG_HOME" value="d://shoplog" /> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <appender name="rollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_HOME}/shop.%d{yyyy-MM-dd}.log</fileNamePattern> </rollingPolicy> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <!-- 日志输出级别 --> <root level="INFO"> <appender-ref ref="rollingFile"/> <appender-ref ref="console" /> </root> </configuration>
-
基于SpringBoot的Java爬虫项目-京东商品页
2020-04-25 00:43:32本文是在学习java爬虫时,跟着视频做的一个小项目,本文会着重介绍其中会遇到的问题及重要代码实现。 -
『Java』京东商品评论爬取(Java爬虫)
2020-07-26 22:59:42这段时间一直在做 Java 爬虫的相关开发,在与众多网站平台(其实也就几个 )的斗智斗勇中也稍有一点心得,今天就使用 Java 爬取一下x东的商品评论信息来记录一下,如果有什么错误或不足之处,也烦请各位大佬指出,... -
Java爬虫爬取京东
2020-08-27 23:26:08首先访问京东,搜索手机,分析页面,我们抓取以下商品数据: 商品图片、价格、标题、商品详情页 SPU和SKU 除了以上四个属性以外,我们发现上图中的苹果手机有四种产品,我们应该每一种都要抓取。那么这里就必须要... -
Java多线程爬虫爬取京东商品信息
2017-07-24 15:44:35前言网络爬虫,是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。爬虫可以通过模拟浏览器访问网页,从而...最近准备做一个电商网站,商品的原型就打算从一些电商网站上爬取,这里使用了HttpClient和Jsoup实 -
Java爬虫爬取京东商品信息
2021-04-22 17:46:11以下内容转载于...Maven地址org.jsoupjsoup1.11.2网页分析:商品布局分析:测试代码实例:importorg.jsoup.Jsoup;importorg.jsoup.nodes.Document;importorg.jsoup.nodes.Element;... -
JavaReptilian:Java爬虫(对京东图书分类、分类明细、商品列表),
2021-04-28 03:27:25Java爬虫(对京东图书分类,分类明细,商品列表), CREATE DATABASE `java_reptilian` CREATE TABLE `booksort` ( `id` int(11) NOT NULL AUTO_INCREMENT, `sort_name` varchar(50) DEFAULT NULL, PRIMARY KEY... -
基于Springboot的网络爬虫-京东商品页
2020-04-05 10:33:09这是基于Springboot的网络爬虫-京东商品页的源码,可供大家免费下载 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而... -
基于SpringBoot的Java爬虫-京东商品页
2020-04-05 10:09:21基于SpringBoot的Java爬虫项目-京东商品页爬取(部分)效果图遇到的各种BUG项目目录结构具体代码详解配置文件添加依赖application.properties文件dao目录下ItemDao类jd.pojo目录下Item类service目录下的... -
JAVA爬取京东手机商品信息(亲测有效)
2020-05-23 10:58:09爬取京东手机商品信息(本人采用JAVA的MVEN工程)用时两天左右 最近喜欢上研究爬虫的问题了,发现还是很好用的,特别是这里运用了SpringBoot框架正是我最近在学的知识。 技术栈:SpringBoot、Mysql、JpaRepository、... -
java爬虫,爬取京东商品信息,基于selenium
2020-09-03 23:10:29引入jar包: <dependency> ...selenium-java</artifactId> <version>3.141.59</version> </dependency> java代码: package com.jd.demo; import org.openqa. -
java爬虫 (三)- 京东案例
2021-06-25 18:26:021,导入数据库 // 创建crawler数据库, 再创建表 ... `spu` bigint(15) DEFAULT NULL COMMENT '商品集合id', `sku` bigint(15) DEFAULT NULL COMMENT '商品最小品类单元id', `title` varchar(100) DEFAULT NULL COM -
京东商品评论数量爬虫源码
2019-08-09 10:26:35c#利用WebClient和WebRequest获取京东网页商品信息评价数、商品价格、活动标语等。 -
Java爬虫Jsoup+httpclient获取动态生成的数据
2020-10-19 21:21:51主要介绍了Java爬虫Jsoup+httpclient获取动态生成的数据的相关资料,需要的朋友可以参考下 -
java爬取京东数据
2018-08-10 09:24:35java爬取京东数据,利用java的dom类,运用request获取前端页面的dom,再通过特定的格式获取对应的标签。 -
基于JAVA的京东商品分布式爬虫系统的设计与实现.pdf
2020-11-19 10:34:10基于JAVA的京东商品分布式爬虫系统的设计与实现.pdf -
Java 爬虫爬取京东、天猫、淘宝商品数据工具类
2021-07-07 09:58:12利用Java实现爬取淘宝、京东、天猫某商品信息。 导入jsoup包 jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和... -
java爬虫练习|爬取京东上的手机商品数据
2021-03-08 01:15:41最近在学习java的爬虫技术,学的是黑马的视频资源,由于是几年前的视频啦,京东页面有些许变化,在此记录我遇到的问题,使用的爬虫技术是httpClient和jsoup,项目搭建使用的springboot+ jpa。首先给出主页的代码:@... -
基于JAVA的京东商品分布式爬虫系统的设计与实现.zip
2021-10-16 23:17:02基于JAVA的京东商品分布式爬虫系统的设计与实现 -
Java爬虫京东(仅作为学习),使用线程池爬取页面数据
2020-12-26 20:33:49爬虫不多做介绍,本文用于对自己入门爬虫的记录 JDK爬虫简单模板 import org.junit.Test; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.... -
Java爬虫入门-基于jsoup采集京东商品数据简单实现
2020-05-23 22:22:58近来,云计算结课要求是要做一个基于Hadoop组件的电商...下面,作为爬虫的入门,我用Jsoup来实现一下京东商品数据的采集。 首先,和任何项目前提一样,新建一个项目,配置好依赖。 <dependency> <groupId& -
Java爬虫爬取 天猫 淘宝 京东 搜索页和 商品详情
2020-01-09 11:08:10Java爬虫爬取 天猫 淘宝 京东 搜索页和 商品详情 先识别商品url,区分平台提取商品编号,再根据平台带着商品编号爬取数据。 1.导包 <!-- 爬虫相关Jar包依赖 --> <dependency> <groupId>org....