当前位置:   article > 正文

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

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

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

后端

mapper类:

  1. package com.learn.reptile.mapper;
  2. import org.apache.ibatis.annotations.Mapper;
  3. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4. import com.learn.reptile.entity.po.Item;
  5. @Mapper
  6. public interface ItemMapper extends BaseMapper<Item> {
  7. }

controller类增加两个方法,craw抓取并保存商品,items分页展示商品数据:

  1. package com.learn.reptile.web.controller;
  2. import java.util.List;
  3. import javax.annotation.Resource;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.PostMapping;
  6. import org.springframework.web.bind.annotation.RequestBody;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  10. import com.baomidou.mybatisplus.core.metadata.IPage;
  11. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  12. import com.learn.reptile.entity.po.Item;
  13. import com.learn.reptile.entity.po.ItemWebsite;
  14. import com.learn.reptile.entity.vo.R;
  15. import com.learn.reptile.mapper.ItemMapper;
  16. import com.learn.reptile.utils.ItemCraw;
  17. @RequestMapping("/item")
  18. @RestController
  19. public class ItemController {
  20. @Resource
  21. ItemMapper itemMapper;
  22. @GetMapping
  23. public R<IPage<Item>> items(Page<Item> page) {
  24. return R.ok(itemMapper.selectPage(page, new QueryWrapper<>()));
  25. }
  26. /**
  27. * 前端指定匹配商品的网址、正则匹配方法,抓取并保存商品
  28. * @param itemWebsite
  29. * @return
  30. */
  31. @PostMapping("craw")
  32. public R craw(ItemWebsite itemWebsite) {
  33. List<Item> items = ItemCraw.parseItemsFromUrl(itemWebsite.getUrl(), itemWebsite.getRegexpStr(), itemWebsite.getStartStr(), itemWebsite.getEndStr());
  34. for(Item item: items) {
  35. //根据淘宝id作重复校验
  36. Item pre = itemMapper.selectOne(new QueryWrapper<Item>().eq("item_id", item.getItemId()));
  37. item.setSource(itemWebsite.getCode());
  38. if(pre==null) {
  39. itemMapper.insert(item);
  40. } else {
  41. item.setId(pre.getId());
  42. itemMapper.updateById(item);
  43. }
  44. }
  45. return R.ok();
  46. }
  47. /**
  48. * 前端指定匹配商品的网址、正则匹配方法,仅作抓取测试
  49. * @param itemWebsite
  50. * @return
  51. */
  52. @PostMapping("test")
  53. public R<List<Item>> test(@RequestBody ItemWebsite itemWebsite) {
  54. return R.ok(ItemCraw.parseItemsFromUrl(itemWebsite.getUrl(), itemWebsite.getRegexpStr(), itemWebsite.getStartStr(), itemWebsite.getEndStr()));
  55. }
  56. }

前端

router,位置:src/router/modules/home.js:

  1. {
  2. path: '/item',
  3. component: Layout,
  4. name: 'item',
  5. meta: {
  6. title: '商品',
  7. },
  8. icon: 'icon-home',
  9. children: [
  10. {
  11. path: 'itemWebsite',
  12. name: 'itemWebiste',
  13. component: () => import('@/views/item_website/index.vue'),
  14. meta: {
  15. title: '网站',
  16. },
  17. },
  18. {
  19. path: 'itemRegexp/:id',
  20. name: 'itemRegexp',
  21. component: () => import('@/views/item_website/regexp.vue'),
  22. meta: {
  23. title: '商品匹配正则',
  24. },
  25. hidden: true,
  26. },
  27. {
  28. path: '',
  29. name: 'item',
  30. component: () => import('@/views/item/index.vue'),
  31. meta: {
  32. title: '商品',
  33. },
  34. },
  35. ],
  36. },

/src/views/item/index.vue,首先写列表部分代码:

html部分

  1. <template>
  2. <div>
  3. <el-table
  4. :data="list"
  5. v-loading="loading"
  6. element-loading-text="Loading"
  7. highlight-current-row
  8. border
  9. fit
  10. >
  11. <el-table-column prop="sourceName" label="采集网站"></el-table-column>
  12. <el-table-column prop="itemId" label="淘宝ID"></el-table-column>
  13. <el-table-column prop="title" label="标题"></el-table-column>
  14. <el-table-column prop="pic" label="图片">
  15. <template #default="scope">
  16. <img :src="scope.row.pic" class="item-img" />
  17. </template>
  18. </el-table-column>
  19. <el-table-column prop="price" label="价格"></el-table-column>
  20. <el-table-column prop="prePrice" label="原价"></el-table-column>
  21. <el-table-column prop="createTime" label="采集时间"></el-table-column>
  22. </el-table>
  23. <el-pagination
  24. :current-page="searchForm.current"
  25. :page-sizes="[20, 45, 80]"
  26. :page-size="searchForm.size"
  27. layout="total, sizes, prev, pager, next, jumper"
  28. :total="total"
  29. :hide-on-single-page="true"
  30. @size-change="pageSizeChange"
  31. @current-change="pageNoChange"
  32. />
  33. </div>
  34. </template>

javascript部分

  1. import { getCurrentInstance, reactive, toRefs, ref, onMounted } from 'vue'
  2. import { list, craw } from '@/api/item'
  3. import { list as websites } from '@/api/itemWebsite'
  4. export default {
  5. setup() {
  6. const { proxy: ctx } = getCurrentInstance()
  7. const state = reactive({
  8. loading: false,
  9. searchForm: {
  10. current: 1,
  11. size: 20,
  12. },
  13. total: 0,
  14. list: [],
  15. getList() {
  16. ctx.loading = true
  17. list(ctx.searchForm).then(res => {
  18. ctx.list = res.data.records
  19. ctx.list.forEach(item => {
  20. ctx.websites.forEach(website => {
  21. if (item.source == website.code) {
  22. item.sourceName = website.name
  23. }
  24. })
  25. })
  26. ctx.total = res.data.total
  27. ctx.loading = false
  28. })
  29. },
  30. pageSizeChange(pageSize) {
  31. ctx.searchForm.size = pageSize
  32. ctx.getList()
  33. },
  34. pageNoChange(pageNo) {
  35. ctx.searchForm.current = pageNo
  36. ctx.getList()
  37. },
  38. })
  39. onMounted(() => {
  40. websites().then(res => {
  41. ctx.websites = res.data
  42. ctx.getList()
  43. })
  44. })
  45. return {
  46. ...toRefs(state),
  47. }
  48. },
  49. }

增加采集按钮和javascript代码:

  1. <el-button type="primary" @click="showCraw">采集</el-button>
  2. <el-dialog
  3. v-model="crawDialogVisible"
  4. title="商品采集"
  5. width="40%"
  6. @close="crawDialogVisible = false"
  7. >
  8. <el-form :model="crawForm" label-position="left">
  9. <el-form-item prop="id" label="采集网站">
  10. <el-select v-model="crawForm.id" clearable placeholder="自定义">
  11. <el-option value="">自定义</el-option>
  12. <el-option
  13. v-for="website in websites"
  14. :key="website.id"
  15. :value="website.id"
  16. :label="website.name"
  17. @click="crawForm = website"
  18. >
  19. {{ website.name }}
  20. </el-option>
  21. </el-select>
  22. </el-form-item>
  23. <el-form-item prop="code" label="网站名称" v-if="!crawForm.id">
  24. <el-input v-model="crawForm.code"></el-input>
  25. </el-form-item>
  26. <el-form-item prop="url" label="URL" v-if="!crawForm.id">
  27. <el-input v-model="crawForm.url"></el-input>
  28. </el-form-item>
  29. <el-form-item>
  30. <el-button type="primary" @click="craw">采集</el-button>
  31. <el-button type="warning" @click="crawDialogVisible = false">
  32. 取消
  33. </el-button>
  34. </el-form-item>
  35. </el-form>
  36. </el-dialog>

javascript部分增加craw和showCraw方法,增加后的完整代码如下:

  1. import { getCurrentInstance, reactive, toRefs, ref, onMounted } from 'vue'
  2. import { list, craw } from '@/api/item'
  3. import { list as websites } from '@/api/itemWebsite'
  4. export default {
  5. setup() {
  6. const { proxy: ctx } = getCurrentInstance()
  7. const state = reactive({
  8. loading: false,
  9. searchForm: {
  10. current: 1,
  11. size: 20,
  12. },
  13. total: 0,
  14. list: [],
  15. websites: [],
  16. crawForm: {
  17. id: '',
  18. code: '',
  19. name: '',
  20. url: '',
  21. },
  22. crawDialogVisible: false,
  23. getList() {
  24. ctx.loading = true
  25. list(ctx.searchForm).then(res => {
  26. ctx.list = res.data.records
  27. ctx.list.forEach(item => {
  28. ctx.websites.forEach(website => {
  29. if (item.source == website.code) {
  30. item.sourceName = website.name
  31. }
  32. })
  33. })
  34. ctx.total = res.data.total
  35. ctx.loading = false
  36. })
  37. },
  38. pageSizeChange(pageSize) {
  39. ctx.searchForm.size = pageSize
  40. ctx.getList()
  41. },
  42. pageNoChange(pageNo) {
  43. ctx.searchForm.current = pageNo
  44. ctx.getList()
  45. },
  46. showCraw() {
  47. ctx.crawDialogVisible = true
  48. },
  49. craw() {
  50. craw(ctx.crawForm).then(res => {
  51. ctx.$message.success('采集完成')
  52. ctx.crawDialogVisible = false
  53. ctx.getList()
  54. })
  55. },
  56. })
  57. onMounted(() => {
  58. websites().then(res => {
  59. ctx.websites = res.data
  60. ctx.getList()
  61. })
  62. })
  63. return {
  64. ...toRefs(state),
  65. }
  66. },
  67. }

代码及演示网站见:正则采集器之一——需求说明-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/938100
推荐阅读
相关标签
  

闽ICP备14008679号