正则采集器之六——商品管理

将采集到的商品保存到数据库中并在后台系统展示,接下来讲解后端和前端代码。

后端

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博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值