我写了一个自动化脚本涨粉,从0阅读到接近100粉丝(一)

简介: 我写了一个自动化脚本涨粉,从0阅读到接近100粉丝

引言


在CSDN写了大概140篇文章,一直都是0阅读量,仿佛石沉大海,在掘金能能频频上热搜的文章,在CSDN一点反馈都没有,所以跟文章质量关系不大,主要是曝光量,后面调研一下,发现情况如下

image.png

好家伙,基本都是人机评论,后面问了相关博主,原来都是互相刷评论来涨阅读量,enen...,原来CSDN是这样的,真无语,竟然是刷评论,那么就不要怪我用脚本了。


效果如下


image.png


puppeteer入门


先来学习一波puppeteer知识点,其实也不难


puppeteer 简介


Puppeteer 是 Chrome 开发团队在 2017 年发布的一个 Node.js 包, 用来模拟 Chrome 浏览器的运行。

Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。 Chromium 和 Chrome区别

在学puppeteer之前我们先来了解下 headless chrome


什么是 Headless Chrome


  • 在无界面的环境中运行 Chrome
  • 通过命令行或者程序语言操作 Chrome
  • 无需人的干预,运行更稳定
  • 在启动 Chrome 时添加参数 --headless,便可以 headless 模式启动 Chrome
alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"  # Mac OS X 命令别名
chrome --headless --disable-gpu --dump-dom https://www.baidu.com               # 获取页面 DOM
chrome --headless --disable-gpu --screenshot https://www.baidu.com    # 截图

查看更多chrome启动参数 英文中文


puppeteer 能做什么


官方称:“Most things that you can do manually in the browser can be done using Puppeteer”,那么具体可以做些什么呢?

  • 网页截图或者生成 PDF
  • 爬取 SPA 或 SSR 网站
  • UI 自动化测试,模拟表单提交,键盘输入,点击等行为
  • 捕获网站的时间线,帮助诊断性能问题
  • ......


puppeteer 结构


image.png

  • Puppeteer 使用 DevTools 协议 与浏览器进行通信。
  • Browser 实例可以拥有浏览器上下文。
  • BrowserContext 实例定义了一个浏览会话并可拥有多个页面。
  • Page 至少有一个框架:主框架。 可能还有其他框架由 iframe 或 框架标签 创建。
  • frame 至少有一个执行上下文 - 默认的执行上下文 - 框架的 JavaScript 被执行。 一个框架可能有额外的与 扩展 关联的执行上下文。


puppeteer 运行环境


查看 Puppeteer 的官方 API 你会发现满屏的 async, await 之类,这些都是 ES7 的规范,所以你需要: Nodejs 的版本不能低于 v7.6.0

bash

npm install puppeteer 
# or "yarn add puppeteer"

Note: 当你安装 Puppeteer 时,它会自动下载Chromium,由于Chromium比较大,经常会安装失败~ 可是使用以下解决方案

  • 把npm源设置成国内的源 cnpm taobao 等
  • 安装时添加--ignore-scripts命令跳过Chromium的下载  npm install puppeteer --ignore-scripts
  • 安装 puppeteer-core 这个包不会去下载Chromium


puppeteer 基本用法


先打开官方的入门demo

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});
  await browser.close();
})();

上面这段代码就实现了网页截图,先大概解读一下上面几行代码:

  1. 先通过 puppeteer.launch() 创建一个浏览器实例 Browser 对象
  2. 然后通过 Browser 对象创建页面 Page 对象
  3. 然后 page.goto() 跳转到指定的页面
  4. 调用 page.screenshot() 对页面进行截图
  5. 关闭浏览器

是不是觉得好简单?


puppeteer.launch(options)


options 参数详解

参数名称 参数类型 参数说明
ignoreHTTPSErrors boolean 在请求的过程中是否忽略 Https 报错信息,默认为 false
headless boolean 是否以”无头”的模式运行 chrome, 也就是不显示 UI, 默认为 true
executablePath string 可执行文件的路劲,Puppeteer 默认是使用它自带的 chrome webdriver, 如果你想指定一个自己的 webdriver 路径,可以通过这个参数设置
slowMo number 使 Puppeteer 操作减速,单位是毫秒。如果你想看看 Puppeteer 的整个工作过程,这个参数将非常有用。
args Array(String) 传递给 chrome 实例的其他参数,比如你可以使用”–ash-host-window-bounds=1024x768” 来设置浏览器窗口大小。
handleSIGINT boolean 是否允许通过进程信号控制 chrome 进程,也就是说是否可以使用 CTRL+C 关闭并退出浏览器.
timeout number 等待 Chrome 实例启动的最长时间。默认为30000(30秒)。如果传入 0 的话则不限制时间
dumpio boolean 是否将浏览器进程stdout和stderr导入到process.stdout和process.stderr中。默认为false。
userDataDir string 设置用户数据目录,默认linux 是在 ~/.config 目录,window 默认在 C:\Users{USER}\AppData\Local\Google\Chrome\User Data, 其中 {USER} 代表当前登录的用户名
env Object 指定对Chromium可见的环境变量。默认为process.env。
devtools boolean 是否为每个选项卡自动打开DevTools面板, 这个选项只有当 headless 设置为 false 的时候有效


puppeteer如何使用


下面介绍 10 个关于使用 Puppeteer 的用例,并在介绍用例的时候会穿插的讲解一些 API,告诉大家如何使用 Puppeteer:


01 获取元素及操作


如何获取元素?

  • page.$('#uniqueId'):获取某个选择器对应的第一个元素
  • page.$$('div'):获取某个选择器对应的所有元素
  • page.$x('//img'):获取某个 xPath 对应的所有元素
  • page.waitForXPath('//img'):等待某个 xPath 对应的元素出现
  • page.waitForSelector('#uniqueId'):等待某个选择器对应的元素出现

Page.$(selector) 获取单个元素,底层是调用的是 document.querySelector() , 所以选择器的 selector 格式遵循 css 选择器规范

Page.$$(selector) 获取一组元素,底层调用的是 document.querySelectorAll(). 返回 Promise(Array(ElemetHandle)) 元素数组.

const puppeteer = require('puppeteer');
async function run (){
    const browser = await puppeteer.launch({headless:false,defaultViewport:{width:1366,height:768}});
    const page = await browser.newPage();
    await page.goto('https://www.baidu.com');
    const input_area = await page.$("#kw");
    await input_area.type("Hello Wrold");
    const search_btn = await page.$('#su');
    await search_btn.click();
}
run();


02 获取元素属性


Puppeteer 获取元素属性跟我们平时写前段的js的逻辑有点不一样,按照通常的逻辑,应该是现获取元素,然后在获取元素的属性。但是上面我们知道 获取元素的 API 最终返回的都是 ElemetHandle 对象,而你去查看 ElemetHandle 的 API 你会发现,它并没有获取元素属性的 API.

事实上 Puppeteer 专门提供了一套获取属性的 API, Page.$eval() 和 Page.$$eval()

Page.$$eval(selector, pageFunction[, …args]), 获取单个元素的属性,这里的选择器 selector 跟上面 Page.$(selector) 是一样的。

const value = await page.$eval('input[name=search]', input => input.value);
const href = await page.$eval('#a", ele => ele.href);
const content = await page.$eval('.content', ele => ele.outerHTML);
const puppeteer = require('puppeteer');
async function run (){
    const browser = await puppeteer.launch({headless:false,defaultViewport:{width:1366,height:768}});
    const page = await browser.newPage();
    await page.goto('https://www.baidu.com');
    const input_area = await page.$("#kw");
    await input_area.type("Hello Wrold");
    const search_btn = await page.$('#su');
    await search_btn.click();
    await page.waitFor('div#content_left > div.result-op.c-container.xpath-log',{visible:true});
    let resultText = await page.$eval('div#content_left > div.result-op.c-container.xpath-log',ele=> ele.innerText)
    console.log("result Text= ",resultText);
}
run();


03 处理多个元素


const puppeteer = require('puppeteer');
async function run() {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: {
      width: 1280,
      height: 800,
    },
    slowMo: 200,
  });
  const page = await browser.newPage();
  await page.goto('https://www.baidu.com');
  const input_area = await page.$('#kw');
  await input_area.type('Hello Wrold');
  await page.keyboard.press('Enter');
  const listSelector = 'div#content_left > div.result-op.c-container.xpath-log';
  // await page.waitForSelector(listSelector);
  await page.waitFor(3 * 1000);
  const list = await page.$$eval(listSelector, (eles) =>
    eles.map((ele) => ele.innerText)
  );
  console.log('List ==', list);
}
run();


04 切换frame


一个 Frame 包含了一个执行上下文(Execution Context),我们不能跨 Frame 执行函数,一个页面中可以有多个 Frame,主要是通过 iframe 标签嵌入的生成的。其中在页面上的大部分函数其实是 page.mainFrame().xx 的一个简写,Frame 是树状结构,我们可以通过page.frames()获取到页面所有的 Frame,如果想在其它 Frame 中执行函数必须获取到对应的 Frame 才能进行相应的处理

const puppeteer = require('puppeteer')
async function anjuke(){
    const browser = await puppeteer.launch({headless:false});
    const page = await browser.newPage();
    await page.goto('https://login.anjuke.com/login/form');
    // 切换iframe
    await page.frames().map(frame => {console.log(frame.url())})
    const targetFrameUrl = 'https://login.anjuke.com/login/iframeform'
    const frame =  await page.frames().find(frame => frame.url().includes(targetFrameUrl));
    const phone= await frame.waitForSelector('#phoneIpt')
    await phone.type("13122022388")
}
anjuke();


05 拖拽验证码操作


const puppeteer = require('puppeteer')
async function aliyun(){
    const browser = await puppeteer.launch({headless:false,ignoreDefaultArgs:['--enable-automation']});
    const page = await browser.newPage();
    await page.goto('https://account.aliyun.com/register/register.htm',{waitUntil:"networkidle2"});
    const frame = await page.frames().find(frame=>{
        console.log(frame.url())
        return frame.url().includes('https://passport.aliyun.com/member/reg/fast/fast_reg.htm')
    })
    const span = await frame.waitForSelector('#nc_1_n1z');
    const spaninfo = await span.boundingBox();
    console.log('spaninfo',spaninfo)
    await page.mouse.move(spaninfo.x,spaninfo.y);
    await page.mouse.down();
    const div = await frame.waitForSelector('div#nc_1__scale_text > span.nc-lang-cnt');
    const divinfo = await div.boundingBox();
    console.log('divinfo',divinfo)
    for(var i=0;i<divinfo.width;i++){
        await page.mouse.move(spaninfo.x+i,spaninfo.y);
    }
    await page.mouse.up();
}
aliyun();

目录
相关文章
|
20天前
|
Linux Shell Perl
自动化脚本之Debian 开机时运行通过expect自动执行串口命令
自动化脚本之Debian 开机时运行通过expect自动执行串口命令
18 0
|
5天前
|
JSON 监控 测试技术
Groovy脚本编写员工上网行为监控自动化测试
本文介绍了如何使用Groovy脚本创建一个自动化工具来监控员工的网络活动。通过编写简单脚本记录员工访问的网站并打印信息,可进一步扩展为将数据保存至数据库。此外,通过设定定时任务,实现了每30分钟自动监控一次的功能。最后,展示了如何将监控数据转换为JSON格式并使用HTTP POST请求提交到网站,以实现数据的自动化上报,有助于企业保障网络安全、保护数据并提升工作效率。
47 5
|
6天前
|
SQL 关系型数据库 MySQL
【简单无脑】自动化脚本一键安装虚拟机下的MySQL服务
该文章提供了在虚拟机上安装MySQL服务的简化方法,特别是针对新手。作者提供了一个自动化脚本`install_mysql.sh`,使得安装过程更简单。用户需要下载`install.rpm`资源,将其放在指定目录下,然后创建并编辑脚本文件,将提供的代码粘贴进去,通过`chmod u+x`授权,最后运行脚本`./install_mysql.sh [rpm文件路径]`来安装MySQL。文章还附有相关图片说明。
17 1
【简单无脑】自动化脚本一键安装虚拟机下的MySQL服务
|
6天前
|
SQL 缓存 关系型数据库
MySQL常见问题解决和自动化安装脚本
这篇内容包含了两个主要部分:解决MySQL登录问题和处理GPG密钥问题。当MySQL密码正确但无法登录时,可以通过执行SQL命令`ALTER USER`和`flush privileges`来修改和重置密码。对于MySQL安装时的GPG密钥错误,首先需要强制删除旧的MySQL仓库包,导入新的GPG公钥,然后安装MySQL服务器。如果遇到GPG检查错误,可以使用`--nogpgcheck`参数忽略检查来安装。最后,提供了一个自动化安装MySQL的脚本,用于检查旧版本、卸载残留、安装MySQL8并启动服务。
22 1
MySQL常见问题解决和自动化安装脚本
|
12天前
|
弹性计算 运维 Shell
|
12天前
|
存储 弹性计算 运维
自动化收集员工信息的Shell脚本
【4月更文挑战第30天】
10 0
|
13天前
|
机器学习/深度学习 人工智能 供应链
【专栏】阿里云RPA的Rap程序是自动化流程脚本,基于AI和机器学习,实现业务流程自动化
【4月更文挑战第29天】阿里云RPA的Rap程序是自动化流程脚本,基于AI和机器学习,实现业务流程自动化。具有灵活性、易用性、高效稳定和智能学习等特点。广泛应用于财务、人力资源、客服和供应链等领域,未来将与AI深度融合,跨平台应用,行业定制化,并构建完善生态,助力企业效率提升和创新。
|
14天前
|
网络协议 安全
【专栏】`curl`是广泛用于网络编程和自动化脚本的命令行工具,支持HTTP、HTTPS等协议
【4月更文挑战第28天】`curl`是广泛用于网络编程和自动化脚本的命令行工具,支持HTTP、HTTPS等协议。在处理大文件或慢速服务器时,设置超时参数至关重要。本文介绍了`curl`的超时参数,如`-m`(最大操作时间)、`-c`(连接超时)、`--dns-timeout`(DNS解析超时)和`-t`(时间条件)。通过示例展示了如何设置这些超时,并提到了一些高级技巧和注意事项,如错误处理和带宽限制。合理设置超时能提高效率和可靠性,对编写健壮的自动化脚本非常有用。
|
19天前
|
Shell
CentOS6.5自动化安装LAMP脚本
CentOS6.5自动化安装LAMP脚本
|
20天前
|
Linux 数据安全/隐私保护
自动化脚本之加密内容解密适用于Linux
自动化脚本之加密内容解密适用于Linux
17 1

热门文章

最新文章