赞
踩
将采集到的商品保存到数据库中并在后台系统展示,接下来讲解后端和前端代码。
mapper类:
- package com.learn.reptile.mapper;
-
- import org.apache.ibatis.annotations.Mapper;
-
- import com.baomidou.mybatisplus.core.mapper.BaseMapper;
- import com.learn.reptile.entity.po.Item;
-
- @Mapper
- public interface ItemMapper extends BaseMapper<Item> {
-
- }
controller类增加两个方法,craw抓取并保存商品,items分页展示商品数据:
- package com.learn.reptile.web.controller;
-
- import java.util.List;
-
- import javax.annotation.Resource;
-
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.baomidou.mybatisplus.core.metadata.IPage;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.learn.reptile.entity.po.Item;
- import com.learn.reptile.entity.po.ItemWebsite;
- import com.learn.reptile.entity.vo.R;
- import com.learn.reptile.mapper.ItemMapper;
- import com.learn.reptile.utils.ItemCraw;
-
- @RequestMapping("/item")
- @RestController
- public class ItemController {
-
- @Resource
- ItemMapper itemMapper;
-
- @GetMapping
- public R<IPage<Item>> items(Page<Item> page) {
- return R.ok(itemMapper.selectPage(page, new QueryWrapper<>()));
- }
-
- /**
- * 前端指定匹配商品的网址、正则匹配方法,抓取并保存商品
- * @param itemWebsite
- * @return
- */
- @PostMapping("craw")
- public R craw(ItemWebsite itemWebsite) {
- List<Item> items = ItemCraw.parseItemsFromUrl(itemWebsite.getUrl(), itemWebsite.getRegexpStr(), itemWebsite.getStartStr(), itemWebsite.getEndStr());
- for(Item item: items) {
- //根据淘宝id作重复校验
- Item pre = itemMapper.selectOne(new QueryWrapper<Item>().eq("item_id", item.getItemId()));
- item.setSource(itemWebsite.getCode());
- if(pre==null) {
- itemMapper.insert(item);
- } else {
- item.setId(pre.getId());
- itemMapper.updateById(item);
- }
- }
- return R.ok();
- }
-
- /**
- * 前端指定匹配商品的网址、正则匹配方法,仅作抓取测试
- * @param itemWebsite
- * @return
- */
- @PostMapping("test")
- public R<List<Item>> test(@RequestBody ItemWebsite itemWebsite) {
- return R.ok(ItemCraw.parseItemsFromUrl(itemWebsite.getUrl(), itemWebsite.getRegexpStr(), itemWebsite.getStartStr(), itemWebsite.getEndStr()));
- }
- }

router,位置:src/router/modules/home.js:
- {
- path: '/item',
- component: Layout,
- name: 'item',
- meta: {
- title: '商品',
- },
- icon: 'icon-home',
- children: [
- {
- path: 'itemWebsite',
- name: 'itemWebiste',
- component: () => import('@/views/item_website/index.vue'),
- meta: {
- title: '网站',
- },
- },
- {
- path: 'itemRegexp/:id',
- name: 'itemRegexp',
- component: () => import('@/views/item_website/regexp.vue'),
- meta: {
- title: '商品匹配正则',
- },
- hidden: true,
- },
- {
- path: '',
- name: 'item',
- component: () => import('@/views/item/index.vue'),
- meta: {
- title: '商品',
- },
- },
- ],
- },

/src/views/item/index.vue,首先写列表部分代码:
html部分
- <template>
- <div>
- <el-table
- :data="list"
- v-loading="loading"
- element-loading-text="Loading"
- highlight-current-row
- border
- fit
- >
- <el-table-column prop="sourceName" label="采集网站"></el-table-column>
- <el-table-column prop="itemId" label="淘宝ID"></el-table-column>
- <el-table-column prop="title" label="标题"></el-table-column>
- <el-table-column prop="pic" label="图片">
- <template #default="scope">
- <img :src="scope.row.pic" class="item-img" />
- </template>
- </el-table-column>
- <el-table-column prop="price" label="价格"></el-table-column>
- <el-table-column prop="prePrice" label="原价"></el-table-column>
- <el-table-column prop="createTime" label="采集时间"></el-table-column>
- </el-table>
- <el-pagination
- :current-page="searchForm.current"
- :page-sizes="[20, 45, 80]"
- :page-size="searchForm.size"
- layout="total, sizes, prev, pager, next, jumper"
- :total="total"
- :hide-on-single-page="true"
- @size-change="pageSizeChange"
- @current-change="pageNoChange"
- />
- </div>
- </template>

javascript部分
- import { getCurrentInstance, reactive, toRefs, ref, onMounted } from 'vue'
- import { list, craw } from '@/api/item'
- import { list as websites } from '@/api/itemWebsite'
-
- export default {
- setup() {
- const { proxy: ctx } = getCurrentInstance()
- const state = reactive({
- loading: false,
- searchForm: {
- current: 1,
- size: 20,
- },
- total: 0,
- list: [],
- getList() {
- ctx.loading = true
- list(ctx.searchForm).then(res => {
- ctx.list = res.data.records
- ctx.list.forEach(item => {
- ctx.websites.forEach(website => {
- if (item.source == website.code) {
- item.sourceName = website.name
- }
- })
- })
- ctx.total = res.data.total
- ctx.loading = false
- })
- },
- pageSizeChange(pageSize) {
- ctx.searchForm.size = pageSize
- ctx.getList()
- },
- pageNoChange(pageNo) {
- ctx.searchForm.current = pageNo
- ctx.getList()
- },
- })
- onMounted(() => {
- websites().then(res => {
- ctx.websites = res.data
- ctx.getList()
- })
- })
- return {
- ...toRefs(state),
- }
- },
- }

增加采集按钮和javascript代码:
- <el-button type="primary" @click="showCraw">采集</el-button>
-
- <el-dialog
- v-model="crawDialogVisible"
- title="商品采集"
- width="40%"
- @close="crawDialogVisible = false"
- >
- <el-form :model="crawForm" label-position="left">
- <el-form-item prop="id" label="采集网站">
- <el-select v-model="crawForm.id" clearable placeholder="自定义">
- <el-option value="">自定义</el-option>
- <el-option
- v-for="website in websites"
- :key="website.id"
- :value="website.id"
- :label="website.name"
- @click="crawForm = website"
- >
- {{ website.name }}
- </el-option>
- </el-select>
- </el-form-item>
- <el-form-item prop="code" label="网站名称" v-if="!crawForm.id">
- <el-input v-model="crawForm.code"></el-input>
- </el-form-item>
- <el-form-item prop="url" label="URL" v-if="!crawForm.id">
- <el-input v-model="crawForm.url"></el-input>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="craw">采集</el-button>
- <el-button type="warning" @click="crawDialogVisible = false">
- 取消
- </el-button>
- </el-form-item>
- </el-form>
- </el-dialog>

javascript部分增加craw和showCraw方法,增加后的完整代码如下:
- import { getCurrentInstance, reactive, toRefs, ref, onMounted } from 'vue'
- import { list, craw } from '@/api/item'
- import { list as websites } from '@/api/itemWebsite'
-
- export default {
- setup() {
- const { proxy: ctx } = getCurrentInstance()
- const state = reactive({
- loading: false,
- searchForm: {
- current: 1,
- size: 20,
- },
- total: 0,
- list: [],
- websites: [],
- crawForm: {
- id: '',
- code: '',
- name: '',
- url: '',
- },
- crawDialogVisible: false,
- getList() {
- ctx.loading = true
- list(ctx.searchForm).then(res => {
- ctx.list = res.data.records
- ctx.list.forEach(item => {
- ctx.websites.forEach(website => {
- if (item.source == website.code) {
- item.sourceName = website.name
- }
- })
- })
- ctx.total = res.data.total
- ctx.loading = false
- })
- },
- pageSizeChange(pageSize) {
- ctx.searchForm.size = pageSize
- ctx.getList()
- },
- pageNoChange(pageNo) {
- ctx.searchForm.current = pageNo
- ctx.getList()
- },
- showCraw() {
- ctx.crawDialogVisible = true
- },
- craw() {
- craw(ctx.crawForm).then(res => {
- ctx.$message.success('采集完成')
- ctx.crawDialogVisible = false
- ctx.getList()
- })
- },
- })
- onMounted(() => {
- websites().then(res => {
- ctx.websites = res.data
- ctx.getList()
- })
- })
- return {
- ...toRefs(state),
- }
- },
- }

代码及演示网站见:正则采集器之一——需求说明-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。