Spring Boot集成WebMagic爬取京东商品信息
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot集成WebMagic爬取京东商品信息相关的知识,希望对你有一定的参考价值。
Spring Boot集成WebMagic爬取京东商品信息
爬取分析
商品列表
访问页面并搜索笔记本电脑
,得到商品列表。
商品详情页
执行流程
graph LR
A[解析商品列表页] ----> B[获取商品详情页]
B ----> C(解析页面获取数据)
搭建基础环境
添加依赖
<!--SpringMVC-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringData Jpa-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--mysql连接包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<!--WebMagic核心包-->
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-core</artifactId>
<version>0.7.5</version>
</dependency>
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-extension</artifactId>
<version>0.7.5</version>
</dependency>
<!--WebMagic对布隆过滤器的支持-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--工具包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
POJO
@Entity
@Table(name = "item")
@Data
public class Item
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//商品标题
private String title;
//商品价格
private Double price;
//商品图片
private String pic;
//商品详情地址
private String url;
//规格
private String standard;
//店铺;
private String shop;
//创建时间
private Date created;
Dao
public interface ItemDao extends JpaRepository<Item,Long>
Service
public interface ItemService
void save(Item item);
@Service
public class ItemServiceImpl implements ItemService
@Autowired
private ItemDao itemDao;
@Override
@Transactional
public void save(Item item)
this.itemDao.save(item);
开启定时任务
在启动类开启定时任务开关,通过启动项目自动执行爬虫任务。
@SpringBootApplication
@EnableScheduling
public class Application
public static void main(String[] args)
SpringApplication.run(Application.class, args);
HttpUtils
@Component
public class HttpUtils
private PoolingHttpClientConnectionManager cm;
public HttpUtils()
this.cm = new PoolingHttpClientConnectionManager();
//设置最大连接数
this.cm.setMaxTotal(100);
//设置每个主机的最大连接数
this.cm.setDefaultMaxPerRoute(10);
/**
* 根据请求地址下载页面数据
*
* @param url
* @return 页面数据
*/
public String doGethtml(String url)
//获取HttpClient对象
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(this.cm).build();
//创建httpGet请求对象,设置url地址
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");
//设置请求信息
httpGet.setConfig(this.getConfig());
CloseableHttpResponse response = null;
try
//使用HttpClient发起请求,获取响应
response = httpClient.execute(httpGet);
//解析响应,返回结果
if (response.getStatusLine().getStatusCode() == 200)
//判断响应体Entity是否不为空,如果不为空就可以使用EntityUtils
if (response.getEntity() != null)
String content = EntityUtils.toString(response.getEntity(), "utf8");
return content;
catch (IOException e)
e.printStackTrace();
finally
//关闭response
if (response != null)
try
response.close();
catch (IOException e)
e.printStackTrace();
//返回空串
return "";
/**
* 设置请求信息
*
* @return
*/
private RequestConfig getConfig()
RequestConfig config = RequestConfig.custom()
//创建连接的最长时间
.setConnectTimeout(1000)
// 获取连接的最长时间
.setConnectionRequestTimeout(500)
//数据传输的最长时间
.setSocketTimeout(10000)
.build();
return config;
自定义Pipeline保存结果
@Component
public class MyDataPipeline implements Pipeline
@Autowired
private ItemService itemService;
@Override
public void process(ResultItems resultItems, Task task)
//获取封装好的商品详情对象
Item itemInfo = resultItems.get("itemInfo");
if (itemInfo != null)
this.itemService.save(itemInfo);
爬虫逻辑实现
@Component
public class JobProcessor implements PageProcessor
@Autowired
private MyDataPipeline myDataPipeline;
@Autowired
private HttpUtils httpUtils;
private int currentPage=1;
private String url ="https://search.jd.com/Search?keyword=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&wq=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&pvid=19a729aac00f4decbacb5de334b3be4e&s=56&click=0&page=";
@Override
public void process(Page page)
// 解析页面,获取商品信息详情的url地址
Selectable css = page.getHtml().css("div#J_goodsList");
List<Selectable> list = page.getHtml().css("div#J_goodsList li").nodes();
if (list.size() == 0)
// 表示商品详情页,解析页面,获取商品详情信息,保存数据
this.saveJobInfo(page);
else
// 表示商品列表页,解析出详情页的url地址,放到任务队列中
for (Selectable selectable : list)
String url = selectable.css("div.p-name").links().toString();
// 把获取到的url地址放到任务队列中
page.addTargetRequest(url);
// 获取下一页的url
currentPage=currentPage+2;
// 把url放到任务队列中
page.addTargetRequest(url+currentPage);
//解析页面,获取商品详情信息,保存数据
private void saveJobInfo(Page page)
// 创建商品详情对象
Item item = new Item();
// 解析页面
Html html = page.getHtml();
// 设置详情页地址
String url = page.getUrl().toString();
item.setUrl(url);
// 商品图片地址
String src = "https://"+html.css("div.preview img", "data-origin").toString();
item.setPic(src);
// 获取名称
item.setTitle(html.css("div.sku-name","text").toString());
// 获取当前选择的sku
String sku = html.css("div#choose-attr-2 div.selected", "data-sku").toString();
// 规格
String standard = html.css("div#choose-attr-2 div.selected", "data-value").toString();
item.setStandard(standard);
// 商品价格,先获取sku,通过接口获取价格
String jsonPrice = httpUtils.doGetHtml("https://" + "p.3.cn/prices/mgets?skuIds=J_" + sku);
JSONObject priceObject = (JSONObject)JSONArray.parseArray(jsonPrice).get(0);
item.setPrice(priceObject.getDouble("p"));
// 店铺名称
String text = html.css("div.popbox-inner a", "text").toString();
// String text2 = Jsoup.parse(html.css("div.popbox-inner a").toString()).text();
item.setShop(text);
item.setCreated(new Date());
// 一个SPU商品里面包含多个SKU商品,每个SKU商品都有自己的价格,所以需要获取每个SKU商品的价格
List<Selectable> nodes = html.css("div#choose-attr-2 div.item").nodes();
for (Selectable node : nodes)
String nodeSku = node.css("div.item","data-sku").toString();
// 排除上述处理的sku对应商品
if (sku.equals(nodeSku))
continue;
page.addTargetRequest("https://item.jd.com/"+nodeSku+".html");
page.putField("itemInfo",item);
private Site site = Site.me()
.setCharset("UTF-8")//设置编码
.setTimeOut(10 * 1000)//设置超时时间
.setRetrySleepTime(3000)//设置重试的间隔时间
.setRetryTimes(3)//设置重试的次数
.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36")//设置请求头
;
@Override
public Site getSite()
return site;
/**
* 定时执行
*
* initialDelay:启动项目延迟执行
* fixedDelay:每隔5s执行一次
*/
@Scheduled(initialDelay = 2000, fixedDelay = 5000)
public void process()
Spider.create(new JobProcessor())
// 初始访问url地址
.addUrl(url+currentPage)
// 使用布隆过滤器
.setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(100000)))
.thread(6)
.addPipeline(this.myDataPipeline)
.run();
执行测试
启动项目,执行查看结果。
以上是关于Spring Boot集成WebMagic爬取京东商品信息的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + WebMagic 实现网页爬虫,写得太好了!