实现一个完整爬虫并爬虫能满足工作流需求使用的工作量其实比较大,本文只是第一个章节,着重于搭建项目脚手架并使用clipsheet在一个网页上探测出可爬取表格的简单例子,更多的内容之后会持续更新

如果你想直接体验univer-clipsheet的功能,而不关心具体实现可以参考这篇文章,这篇文章更着重介绍了如何使用univer-clipsheet。

一款更简单好用的Chrome爬虫插件 - Univer Clipsheet-CSDN博客

本文的功能都是基于 univer-clipsheet 开源项目提供的能力去完成一个简单的爬虫项目,univer-clipsheet的能力的实现代码实际是在 univer-clipsheet-core 的仓库下,接下来我们会在项目中引入univer-clipsheet-core去帮助我们完成一个从网页中采集表格的工作。

1. 初始化项目

我们推荐直接用chrome-extension-boilerplate-react-vite作为我们插件项目的脚手架,执行以下命令初始化项目,git submodule add是将我们的univer-clipsheet-core引入到项目中

git clone https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite.git
cd chrome-extension-boilerplate-react
git submodule add https://github.com/dream-num/univer-clipsheet-core submodules/univer-clipsheet-core

找到pnpm-workspace.yaml文件并新增一行

- 'submodules/univer-clipsheet-core/packages/**'

执行命令pnpm i去安装依赖

pnpm i

安装依赖完毕后执行以下命令运行插件

pnpm dev

成功运行后,打开项目的文件夹,会看到一个dist文件夹,打开chrome浏览器或者其他浏览器的扩展管理页面,加载dist文件夹。
关于浏览器怎么通过文件夹安装插件可以参考这篇文章在github下载chrome扩展文件压缩包后怎么添加扩展到chrome(chrome添加hackbar扩展)_github插件 装 chrome-CSDN博客
加载成功后,可以看到浏览器右上角已经显示该插件,作者这里以chrome为例,其他浏览器的入口所在位置也大径相同。

2. 查找网页中的表格

我们回到项目代码中,导航到 pages/content目录,并给package.json中声明univer-clipsheet-core的依赖

"@univer-clipsheet-core/table": "workspace:*"

结束项目运行,重新执行以下命令,安装依赖以及重新运行

pnpm i && pnpm dev

导航到pages/content/index.ts文件中,添加如下代码保存,并刷新当前正在浏览的网页并打开浏览器控制台。

import type { IInitialSheet, ITableApproximationExtractionParam } from '@univer-clipsheet-core/table';
import { findApproximationTables, LazyLoadElements, LazyLoadTableElements } from '@univer-clipsheet-core/table';
// 该方法可以将table标签元素转换为IInitialSheet对象
function generateSheetByElement(element: HTMLTableElement) {
  return new LazyLoadTableElements([element]).getAllSheets();
}
// 该方法可以将ExtractionParams对象转换为IInitialSheet对象
function generateSheetByExtractionParams(params: ITableApproximationExtractionParam) {
  return new LazyLoadElements([params]).getAllSheets();
}
 
window.addEventListener('load', () => {
  const tableElements = document.querySelectorAll('table');
  // 从body自上往下查找可能包含表格的元素(例如ui、li等列表标签),并生成ExtractionParams对象
  const extractionParamsList = findApproximationTables(document.body as HTMLBodyElement);
 
  const allInitialSheets: IInitialSheet[] = [];
  // 遍历table标签元素,生成IInitialSheet对象
  tableElements.forEach(element => {
    const sheets = generateSheetByElement(element as HTMLTableElement);
    allInitialSheets.push(...sheets);
  });
  // 遍历ExtractionParams对象,生成IInitialSheet对象
  extractionParamsList.forEach(params => {
    const sheets = generateSheetByExtractionParams(params);
    allInitialSheets.push(...sheets);
  });
 
  allInitialSheets
    // 过滤掉行数小于5的表格
    .filter(sheet => sheet.rows.length > 5)
    .forEach((sheet, sheetIndex) => {
      console.log(`Sheet ${sheetIndex + 1} :`, sheet, 'sheet rows: ', sheet.rows);
    });
});

代码中已经添加了注释,注释说明了没行代码的执行发生了什么。
接下来,我们以react仓库的issue页面Issues · facebook/react · GitHub为例Issues · facebook/react · GitHub,跳转到页面并打开控制台,我们可以看到控制台打印出了我们在这个网页中探测到的表格数据!

InitialSheet

initialSheet是univer-clipsheet对表格的描述,大概关于initialSheet的类型定义我贴在下面

interface IInitialSheet {
    sheetName: string;
    columnName: string[];
    rows: ISheet_Row[];
    type: Initial_Sheet_Type_Num;
    density: number;
    cellCount: number;
    weightedScore?: number;
    selectorString?: string;
}
interface ISheet_Row {
    cells: ISheet_Row_Cell[];
}
interface ISheet_Row_Cell {
    type: Sheet_Cell_Type_Enum;
    text: string;
    url: string;
}

从类型定义我们可以看到,实际表格每个单元格的时候以SheetRowCell的类型定义,如果是文本元素我们会把值放在text字段上,如imgavideo等标签,我们会解析它的资源放在url字段上。

结语:

以上就是我们通过univer-clipsheet开源能力做到的第一步,探测当前网页中的表格,其实这也就是爬虫需要做的事,采集网页中的某一个表格,并加上更多自动化、定制化的能力,univer-clipsheet提供了很多能力来帮我们做到这些事,大家感兴趣可以关注,这个系列会继续更新~

有任何问题及建议也可在github提issue或直接通过discord联系我们~


梦数技术团队
1 声望6 粉丝

上海梦数科技有限公司(简称:梦数科技)成立于2019年,是一家具有国际化视野的高科技公司,专注于提供先进的数字化解决方案,以“串联数据,加速工作流,让业务更高效”为使命,通过全面的软件开发工具,致力于帮...