这个项目本身使用Aurora Vision提供的api进行爬虫,但Aurora Vision更新了他们的api版本,并且需要申请额外服务,因此该项目只能从网页基于puppeteer进行爬虫。

puppeteer是一个很容易上手的爬虫库,基本看quick start就能理解其是如何模拟人的一些操作来爬虫的。该项目的难点在于我不会java,也不会js,熟悉这些花费了很久的时间。

node.js和puppeteer安装

先装npm,后装puppeteer,挺简单的

node.js的调试

console.log('this is test') 控制台输出

console.time('puppeteer')
console.timeLog('puppeteer')
console.timeEnd('puppeteer') 计算时间

node inspect xxx.js: 内置的检查器

cont, c: 继续执行

next, n: 下一步

step, s: 进入

out, o: 走出去

pause:暂停运行代码(如开发者工具中的暂停按钮)

参考node.js 官方文档

在vs中设置js的debug环境vs nodejs

youtube视频教程Getting started with Node.js debugging in VS Code

在vs中debug:在控制台输入noed xxx.js之后即可打开debug页面。 vs inline value: Open Settings Search for “debug” Navigate to Features > Debug Change the setting for Debug: Inline Values

另外还可以使用devtool等方法。我觉得还是vs最方便。

node.js的一些迷惑语法

module exports: 模块化。

很多时候一个文件会被包装成一整个模块,直接对其debug是不会有反映的。要在别的test文件中导入,再逐行debug。 例如 #./scraper.js module.exports = {}

#./test.js
const test = require('./scraper')
data = test.execute()
console.log(data)

return多个值

return[1,2,3,4]

删除某个元素

#从末尾删除一个元素
array.pop()

#从开头删除一个元素
array.shift()

#从某位置删除几个
array.splice(0,2)

#使用filter
filter() 有一个参数,一个回调方法。当 filter 方法遍历数组元素时触发回调。它会将三个值传递给回调:当前值或元素、当前数组索引和完整数组。
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
var filtered = array.filter(function(value, index, arr){ 
    return value > 5;
});

判断数组是否为空

没有直接的isnull这种用法。可以用!array.length判断

一些js表达式

参考这个可以直接运行的网站mozilla-js

puppeteer的调试

设置headless以及devtools,在浏览器中执行调试。

const browser = await puppeteer.launch({
  args: ['--no-sandbox', '--disable-setuid-sandbox'],
  headless:false,
  devtools: true,
  ignoreHTTPSErrors: true
});

puppeteer的一些语法

官方文档page

获取元素page.$() page.$$()

首先,page上的所有可执行元素称作element node,只能对其进行操作。

使用page.$() 以及page.$$() 选择所需要的元素。

selector有很多种类

根据type const n = await page.$(“h4”)

根据name const f = await page.$(’[name=“search”]')

根据class name const f = await page.$(".heading")

根据id const f = await page.$("#id")

根据arrtibute(tag name and attribute name) const n = await page.$(“li[class=‘heading’]”)

另一种是根据Xpath,使用page.$x(),xpath可以直接在devtool中获得。

注意:有的页面加载很慢,需要先确保页面元素存在再进行选择。

page.waitForTimeout(10000)

单位为ms。为了反反爬虫,最好设置的大一些。

innerText

一般先获取td列表,对于每一个获取td.innerText const data = await page.$$eval(’table tr td’, tds => tds.map((td) => { return td.innerText; }));

page.type

大致是输入的意思,把value输入某个可选择对象

page.click

这里有个牛逼的操作 await page.click(’[name=“comboBoxInput”]’,{ clickCount: 3 }); await page.type(’[name=“comboBoxInput”]’, plant_name); 模拟点击三次文本框,接着使用type,可以直接输入所需要的值。

评估函数

使用page.evaluate()获取内部的函数值。 常常与=>这个js中的lambda表达式联合使用。 例如 const plantNames = await page.evaluate(() => { const tds = Array.from(document.querySelectorAll(’.app-tree-clickable ‘)).map(td => td.innerText); return tds.filter(function(value,index) { return value.length < 17; }) })

map和filter

我的理解: map(x => x.function) <==> apply(lambda x:func(x)) filter(x => {return limit_function(x)}) <==> apply(lambda x:func(x))

Array from

获取数组(列表)

转置矩阵

虽然没看懂 const arrayT = await array[0].map((_, colIndex) => array.map(row => row[colIndex]))