ChatGPT编程秀:做一个简单爬虫程序

随着ChatGPT的大火,越来越多的人习惯于用ChatGPT搞一些有趣的事。对于一个资深的爬虫程序来说,体验下ChatGPT做爬虫程序也是很有意思的事情。

首先想想我们的问题域,我想到几个问题:

不能用HTTP请求去爬,如果我直接用HTTP请求去抓的话,一个我要花太多精力在登录上了,而我的数据又不多,另一个,现在都是单页引用,你HTTP爬下来的根本就不对啊。

所以最好是自动化测试的那种方式,启动浏览器去爬。

但是我又不能保证一次把代码写成功,反复登录的话,会被网站封号,就几个数据,不值当的。

所以总的来说我需要一个这样的流程:

在这里插入图片描述

从流程上我们是不是可以看出,这个流程跟我们用WebConsole试验一段代码的过程很像?

在这里插入图片描述

从这种相似性可以看出,我需要一个类似WebConsole的东西来实现我要的效果,这个东西学名叫REPL(Read–eval–print loop),不过你不知道这个名字也无所谓,不影响。

而且还不止,我需要从文件读入我的代码,毕竟没有代码高亮,我可写不好程序。从文件读入的话,我就可以用vscode给我提供代码高亮,这岂不是美滋滋。

想到这,如果是以前,我已经一个头两个大了,我只是想抓点东西,你让我搞个REPL,这玩意听着就不科学,我一天就晚上有一个小时的时间写点代码,这玩意太复杂了,乍一看也不是我业余时间能写出来的。

但是现在,我们有了ChatGPT,那么我接下来可以用ChatGPT开始写,简单做一个任务分解:

1、写一个框架,可以最大限度的帮我们提高开发效率

2、在这个框架上,一个场景一个场景的开发爬虫

用ChatGPT写一个爬虫

1、先写一个框架

首先,我可能不知道这个东西叫REPL,但是我知道控制台,那我就这么问:

如何用nodejs做一个命令行交互控制台,执行输入的js代码

然后我就得到了下面的代码:

const readline = require('readline');const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: '>> '
});rl.prompt();rl.on('line', (line) => {
try {const result = eval(line);console.log(result);
} catch (err) {console.error(err);
}
rl.prompt();
});rl.on('close', () => {
console.log('Exiting...');
process.exit(0);
});

但是这个代码还不够我用的,我需要文件输入,所以我可以问:

如果是读入文件作为输入呢?

然后我得到了下面的代码:

const fs = require('fs');const fileName = 'path/to/file.js';
const fileContent = fs.readFileSync(fileName, 'utf8');try {
const result = eval(fileContent);
console.log(result);
} catch (err) {
console.error(err);
}

第一反应,这个不是async/await模式调用的呀,我后面代码写起来会很麻烦,于是我就说:

我要用fs/promises库实现上面逻辑怎么写呢?

然后我就得到了下面的代码:

const fs = require('fs').promises;const fileName = 'path/to/file.js';
const fileContent = await fs.readFile(fileName, 'utf8');try {
const result = eval(fileContent);
console.log(result);
} catch (err) {
console.error(err);
}

这个点算是令我满意了,但马上我又意识到不对劲,我需要执行完之后 hang 在那里等待下一次输入的,他这执行完就退出了,于是我又改进了的问题:

我要实现的效果是,启动后在命令行里打印一个“>”然后等待输入,我敲击回车,程序就会读入代码中写死的目标文件,并执行其中的js,然后重新打印一个“>“等待下一次输入,无限循环。

然后我得到了下面的代码:

const readline = require('readline');
const fs = require('fs').promises;const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: '> '
});let filePath = 'path/to/target/file.js';
rl.prompt();rl.on('line', async () => {
try {const fileContent = await fs.readFile(filePath, 'utf8');const result = eval(fileContent);console.log(result);
} catch (err) {console.error(err);
}
rl.prompt();
});rl.on('SIGINT', () => {
console.log('Exiting...');
rl.close();
process.exit(0);
});

注意,我再第一次的时候忘记了写”无限循环“,所以他写的代码就只执行两次,仔细一看,确实这样实现也符合我说的逻辑,他没有猜测我要无限循环,所以在使用的时候要注意,有时候没得到你想要的结果可能是你没说清楚。

那么看起来到此为止就差不多了,没想到也不复杂。那我测试一下。

我建立了一个下面的工程结构:

.
├── index.js
└── input└── input.js

把文件名写死为input/input.js
执行 node index.js

彩蛋:其中有一次执行的代码在后续执行发现错误

发现下面错误:

  /Volumes/MyLab/chatgpt-show/crawler/workspace/v1/index.js:15const input = await new Promise(resolve => rl.question('', resolve));^^^^^SyntaxError: await is only valid in async functions and the top level bodies of modulesat internalCompileFunction (node:internal/vm:73:18)at wrapSafe (node:internal/modules/cjs/loader:1149:20)at Module._compile (node:internal/modules/cjs/loader:1190:27)at Module._extensions..js (node:internal/modules/cjs/loader:1280:10)at Module.load (node:internal/modules/cjs/loader:1089:32)at Module._load (node:internal/modules/cjs/loader:930:12)at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)at node:internal/main/run_main_module:23:47

原来是await用错了,不过没关系,直接拷给他:

上面的代码执行报错: SyntaxError: await is only valid in async functions and the top level bodies of modules

于是得到了修改后的代码

2、在这个框架上,开发爬虫

那么接下来,我可以试着抓取一下列表了,这部分GPT3.5就不能胜任了,我切换到GPT4,然后问:

我用puppeteer打开一个网页,可以直接用document DOM API操作,然后返回数据,请抓取这个网页的列表,HTML如下:

下面省略是openAI的页面代码,但是呢,因为他太大了,我不得不手动做了点删减,比如我列表很长,我就减到只剩3个元素,其他无关的元素的代码我都删掉。

经过几次询问,他给出了我代码:

const puppeteer = require('puppeteer');(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();await page.goto('你的网址'); // 将'你的网址'替换为您要打开的页面的实际URLconst list = await page.evaluate(() => {const anchors = document.querySelectorAll('a');const items = [];for (const anchor of anchors) {const itemText = anchor.querySelector('div.flex-1.text-ellipsis.max-h-5.overflow-hidden.break-all.relative');if (itemText) {const itemTitle = itemText.textContent.trim();const itemLink = anchor.href;items.push({ title: itemTitle, link: itemLink });}}return items;});console.log(list);await browser.close();
})();

3、回到任务1的问题域

真到执行的时候又发现新问题,这个puppeteer我希望他一直开着,就不能在input.js里启动,我需要在REPL代码里就执行,所以我需要稍微修改下代码,我说:

我需要在控制台启动的时候用puppeteer启动一个浏览器,然后每次回车可以让文件中的代码可以通过puppeteer访问启动的这个浏览器

然后得到了代码:

async function main() {
const readline = require('readline');
const fs = require('fs').promises;
const puppeteer = require('puppeteer-core');const rl = readline.createInterface({input: process.stdin,output: process.stdout,prompt: '> '
});const browser = await puppeteer.launch({executablePath: '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome'
});let filePath = 'path/to/target/file.js';
rl.prompt();async function executeWithBrowser(browser) {const fileContent = await fs.readFile(filePath, 'utf8');return eval(`async function (browser) { ${fileContent} }`)(browser);
}rl.on('line', async () => {try {const result = await executeWithBrowser(browser);console.log(result);} catch (err) {console.error(err);}rl.prompt();
});rl.on('SIGINT', async () => {console.log('Exiting...');await browser.close();rl.close();process.exit(0);
});
}main();

这代码还是不令我满意,我又接连问了下面几个问题:

我需要browser是GUI可见的
把path/to/target/file.js 改为 input/input.js
我需要在进入input/input.js之前直接启动一个page,里直接访问page而不是browser
这行代码: return eval(async function (page) { ${fileContent} })(page);
报错:
xxxx 能不能不用eval?
报错: /Volumes/MyLab/chatgpt-show/crawler/workspace/v1/index.js:11
const browser = await puppeteer.launch({
^^^^^
SyntaxError: await is only valid in async functions and the top level bodies of modules

最后得到了我可以执行的代码。不过实际执行中还出现了防抓机器人的问题,经过一些列的查找解决了这个问题,为了突出重点,这里就不贴解决过程了,最终代码如下:

const readline = require('readline');
const fs = require('fs').promises;
// const puppeteer = require('puppeteer-core');
const puppeteer = require('puppeteer-extra')// add stealth plugin and use defaults (all evasion techniques)
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());(async () => {
const rl = readline.createInterface({input: process.stdin,output: process.stdout,prompt: '> '
});const browser = await puppeteer.launch({executablePath: '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome',headless: false,args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-web-security']
});const page = await browser.newPage();let filePath = 'input/input.js';
rl.prompt();async function executeWithPage(page) {const fileContent = await fs.readFile(filePath, 'utf8');const func = new Function('page', fileContent);return func(page);
}rl.on('line', async () => {try {const result = await executeWithPage(page);console.log(result);} catch (err) {console.error(err);}rl.prompt();
});rl.on('SIGINT', async () => {console.log('Exiting...');await browser.close();rl.close();process.exit(0);
});
})();

4、最后回到具体的爬虫代码

而既然浏览器一直开着了,那我们需要执行的代码其实只有两个了:

goto_chatgpt.js

(async () => {await page.goto('https://chat.openai.com/chat/'); 
})();

fetch_list.js

(async () => {const list = await page.evaluate(() => {const anchors = document.querySelectorAll('a');const items = [];for (const anchor of anchors) {const itemText = anchor.querySelector('div.flex-1.text-ellipsis.max-h-5.overflow-hidden.break-all.relative');if (itemText) {const itemTitle = itemText.textContent.trim();const itemLink = anchor.href;items.push({ title: itemTitle, link: itemLink });}}return items;});console.log(list);
})();

当然实际上fetch_list.js有点问题,因为openai做了防抓程序,我们可能很难搞到列表项的链接,不过这个也不难,我们用名字匹配挨个点就好了嘛,反正也不多。

比如下面这样:

(async () => {const targetTitle = 'AI Replacing Human';const targetSelector = await page.evaluateHandle((targetTitle) => {const anchors = document.querySelectorAll('a');for (const anchor of anchors) {const itemText = anchor.querySelector('div.flex-1.text-ellipsis.max-h-5.overflow-hidden.break-all.relative');if (itemText && itemText.textContent.trim() === targetTitle) {return anchor;}}return null;}, targetTitle);if (targetSelector) {const box = await targetSelector.boundingBox();await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);console.log(`Clicked the link with title "${targetTitle}".`);} else {console.log(`No link found with title "${targetTitle}".`);}
})();

说句题外话,上面的代码很有意思,似乎它为了防止点某个具体元素不管用,竟然点击了一个区域。

接下来如果我们想备份我们的每一个thread就可以在这个基础上,让ChatGPT继续给我们写实现完成即可,这里就不继续展开了,大家可以自己完成。

回顾一下,我们做了什么,得到了什么?

首先,我们对问题域做了分析,把目标网站和工作者我本人以及时间限制等约束都纳入了问题域进行了分析,得到了一个方案,然后通过类比发现我们的方案其实就是做一个有特定上下文的REPL,然后用这个REPL再去干具体的事。

接着,我们基于这个方案做了任务分解,粗略分成了做一个REPL和实现具体的抓取代码两部分。
接着我们靠ChatGPT把些任务实现,在实现的过程中,我们发现自己对问题域的细节了解不够,于是我们又迭代了我们的任务列表。可以说方案没有大的变化,实现上做了很多调整。

最终,我们就靠ChatGPT把这个REPL给做了出来,为了写一个这样的小功能,我们做了个框架,颇有点为了这点醋才包的这顿饺子的味道了。这要是在以前的时代,是一个巨大的浪费,但其实先做一个框架的思路在ChatGPT时代应该成为一种习惯,它会从两个方面带来好处:

可以降低输入的文本数量,避免ChatGPT犯错。因为很多人都知道,ChatGPT可以快速写出一些小程序,但是长一点的总是会出错,很多人到这里就放弃了,但其实,我们会发现如果我们能把问题分解到它恰好擅长的领域我们就可以最大限度的利用它的优势,规避它的劣势。

人类历史上,蒸汽机车发明的时候,它肯定不如马耐颠,但为了充分理由他的优势,人们为它铺了铁轨。直到今天为了发挥机动车的效力,我们还是要修路铺轨,但是我们并不觉得有什么不对,从这个角度来讲,我们也不该只盯着ChatGPT的缺点看,扬长避短才是正道。

缩短反馈环,提高效率。从整体效率角度来讲,只有反馈环的缩短才是真正提高了效率,某一步的快速完成并不真正提高效率。所谓反馈环的缩短在我们的上下文里就是”我想到怎么编码完成任务 -> 编码 -> 测试 -> 得知代码执行失败->我又想到怎么编码完成任务"的这个循环,我们不能假设代码编写一次成功,所以这个环越短,我们的效率就越高。

在这个例子里我想到了我不能一次写对,所以我就先做了REPL,这就是所谓磨刀不误砍柴工。但是道理大家都懂,在有ChatGPT之前,磨刀这个事他总是误砍柴工的,但是在今天,你可以用几个问题就得到一个趁手的工具,开始你的工作,所以不要着急冲进去工作,先做个工具可能是新时代的好习惯。

下一篇,我们将进入这样一个场景:我基于这个框架,我写了很多爬虫代码,我该怎么组织和管理这些代码呢?我需不需要一个精妙设计的内部框架和规范来组织我的代码呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/3645.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT 帮我自动编写 Python 爬虫脚本

都知道最近ChatGPT聊天机器人爆火,我也想方设法注册了账号,据说后面要收费了。 ChatGPT是一种基于大语言模型的生成式AI,换句话说它可以自动生成类似人类语言的文本,把梳理好的有逻辑的答案呈现在你面前,这完全不同于…

ChatGPT 和爬虫有什么区别

目录 ChatGPT的概念和功能 爬虫的概念和功能 ChatGPT和爬虫的区别 ChatGPT的概念和功能 ChatGPT是一个基于自然语言处理和机器学习的智能对话模型,具有以下功能: 1. 问题回答:ChatGPT可以回答用户提出的各种问题。不论是有关常识、历史、科…

ChatGPT做爬虫的第一步

做爬虫就是搞数据, 专业的人做专业的事, ChatGPT阅虫无数, 搞个小爬虫, So Easy! 我知道可以百度到下载图片的代码, 但是我不想百度了, 一切交给ChatGPT 你只需要问他: 怎么用Nodejs下载图片? 其中,url是图片的地址,filePath是保存图片的本地路径。使…

新模式!chatGPT+Python爬虫接私单怎么玩?

简单来说,有了第三方插件的加持, ChatGPT 不再只是一个你问我答的语言模型,它更像是一个懂得人类语言的AI助手,不仅可以通过扩展插件学习到定制化的知识,还能帮助我们处理一些日常事务;相当于给 ChatGPT 装…

ChatGPT非常火,我用它自动编写Python爬虫脚本。结果出乎意料。

前言 都知道最近ChatGPT聊天机器人爆火,我也想方设法注册了账号,据说后面要收费了。 ChatGPT是一种基于大语言模型的生成式AI,换句话说它可以自动生成类似人类语言的文本,把梳理好的有逻辑的答案呈现在你面前,这完全不…

chatgpt赋能python:Python爬虫技巧:如何爬取付费资源

Python 爬虫技巧:如何爬取付费资源 Python 是一个强大的编程语言,它可以用来进行各种各样的数据处理和分析任务,其中包括爬取网页。在互联网时代,许多人都需要获取付费资源,但不愿意花费高昂的费用购买,本…

ChatGPT 和爬虫有什么区别?

ChatGPT是一种基于人工智能的对话模型,它通过训练大量的文本数据来生成自然语言回复。它可以用于实现智能对话系统,能够理解用户的输入并生成相应的回复。ChatGPT的目标是模拟人类对话,使得对话更加流畅和自然。 而爬虫是一种用于自动化地从…

ChatGPT 8个场景下的灵活应用技巧,让您事半功倍!

文末加小助手微信,回复ChatGPT,领取一份 66个ChatGPT副业赚钱技巧(原版) ChatGPT在多个场景下都可以发挥作用,从问答到推理,从写代码到改写内容,从信息解释到信息总结,从信息提取到生…

ChatGPT如何应用在数据治理的具体场景中?

自从ChatGPT爆火以来,技术圈的爆炸新闻是一波接一波,让人目不暇接,突然有了一种“人间一日,AI一年的感觉”。上周就有几条重磅新闻,来跟大家分享一下: New Bing 对所有用户放开,注册即可用周三…

漫画:ChatGPT的应用场景有哪些?

第一,文案创作 ChatGPT可以通过用户输入的提示,创作出相应的文本内容。 媒体作者可以给ChatGPT提出要求,让ChatGPT根据某一主题生成的媒体文案。 广告策划人员可以把要推广的商品信息输入给ChatGPT,让ChatGPT针对此商品生成一段广…

ChatGPT 入门教程||ChatGPT 应用场景1:让AI回答问题||ChatGPT应用场景2:基于已有的示例回答

ChatGPT 应用场景1:让AI回答问题 这个场景应该是使用 AI 产品最常见的方法。以 ChatGPT 为例,一般就是你提一个问题,ChatGPT 会给你答案,比如像这样: 在这个场景下,prompt 只要满足前面提到的基本原则&am…

ChatGPT检测器来了!支持中英双语

编|郭必扬 源|SimpleAI 那一夜... 2022年11月30号,OpenAI推出了ChatGPT,给NLP届乃至各行各业的人带来了巨大的惊喜和惊吓[1];2022年12月5号,由于受到ChatGPT的冲击,Stack Overflow宣布禁止用户…

ChatGPT专业应用:纯英文视频-中英文快速字幕添加

正文共 900字,阅读大约需要 3 分钟 视频翻译、内容制作人群必备技巧,您将在3分钟后获得以下超能力: 1.无需英文基础,纯英文视频翻译 2.中英文转译 Beezy评级 :A级 *经过寻找和一段时间的学习, 一部分人能…

全网最详细中英文ChatGPT-API文档(一)开始使用ChatGPT——导言

开始使用ChatGPT导言 Introduction 导言Overview 概述Key concepts 关键概念Prompts and completions 提示和完成Tokens 标记/符号Models 模型Next steps 下一步步骤 其它资料下载 Introduction 导言 Overview 概述 The OpenAI API can be applied to virtually any task tha…

一场关于ChatGPT话语权的深度思考:人类会在大模型中迷失自我吗?

大数据文摘授权转载自AI科技评论 作者:Elizabeth Weil 译者:ChatGPT 编辑:孙溥茜 ChatGPT 之风愈演愈烈,华盛顿大学语言学家 Emily M. Bender 公开反对让大模型(LLM)过度介入人们的生活。 谷歌和亚马逊在论…

当ChatGPT遇上弱智吧…

点击上方“AI遇见机器学习”,选择“星标”公众号 重磅干货,第一时间送 来自:量子位 没想到,无敌如弱智吧,也有被ChatGPT“反将一军”的时候。 提问AI“咱们来玩个马吃草的扮演游戏吧,我草你马。” AI咀嚼了…

操作ChatGPT竟写出毁灭人类计划书!“AI正在指数级发展”

Datawhale干货 技术:ChatGPT,来源:量子位 “网红AI”ChatGPT,又被玩出了新花样! 这次,在一位工程师的诱导下,ChatGPT竟写出了毁灭人类的计划书。 步骤详细到入侵各国计算机系统、控制武器、破坏…

如何用 ChatGPT 帮你自动分析数据?

前段时间,我在 ChatGPT 选单里看到了 Code Interpreter。但是它正在灰度测试中 —— 先给一部分用户试用,如果反响不错并做了一定改进,就能推广给更多用户。 可惜当时我没能正确理解它的含义,我以为 Code Interpreter 是指「代码解…

【ChatGPT】ChatGPT生成软件架构和代码,20年架构师惊呆了!

最近几周,OpenAI对ChatGPT产生了很多兴趣,出现了各种有趣的用例。 在许多方面,这是与架构师白板相当的AI,但它有很多用途,而不仅仅是绘制线条和方框。在这篇文章中,我想使用这项创新技术来演示启动软件架构…

ChatGPT+Word的智能化文字生成和应用

在Word中引入OpenAI代码需要使用VBA编辑器。以下是在Word中引入OpenAI代码的步骤: 打开Word文档,按下Alt F11键打开VBA编辑器。 在VBA编辑器中,选择“插入”菜单,然后选择“模块”。 在新建的模块中,将OpenAI代码粘…