钥匙要点
- >利用node.js和npm有效地为Web爬网和其他命令行任务设置自定义CLI缩影。
> >使用Phantomjs和Horseman软件包来模拟浏览器中的用户互动,从而增强了自动化的Web爬行功能。 - 结合了骑士方法的链接,以执行复杂的动作序列,从而在网页中进行动态交互。
- 利用骑士中的evaluate()方法直接从DOM中提取灵活的脚本和数据提取,可用于诸如污损检测之类的任务。
- >利用Horseman的屏幕截图功能在网上爬行期间捕获和保存屏幕截图,以帮助视觉QA测试等任务。
- >确保每次使用后都关闭骑士实例,以防止孤立的phantomjs过程,保持系统性能和稳定性。
- >
可以在GitHub上找到本教程的源代码。为了运行示例,您需要同时安装node.js和phantomjs。可以在此处找到用于下载和安装的说明:node.js,phantomjs。
>设置基本命令行框架任何CLI框架的核心是将命令转换为一个或多个可选或必需的参数,转换为具体操作的概念。在这方面非常有用的两个NPM软件包是指挥官和提示。
指挥官允许您定义支持哪些参数,同时提示允许您(足够适当地)提示用户在运行时输入。最终结果是一个句法甜蜜的界面,用于基于某些用户提供的数据,以动态行为执行各种动作。
>说,例如,我们希望我们的命令看起来像这样:
>$ <span>node run.js -x hello_world </span>
我们的入口点(run.js)定义了这样的参数:
>program <span>.version('1.0.0') </span> <span>.option('-x --action-to-perform [string]', 'The type of action to perform.') </span> <span>.option('-u --url [string]', 'Optional URL used by certain actions') </span> <span>.parse(process.argv); </span>
并定义了这样的各种用户输入案例:
><span>var performAction = require('./actions/' + program.actionToPerform) </span> <span>switch (program.actionToPerform) { </span> <span>case 'hello_world': </span> prompt<span>.get([{ </span> <span>// What the property name should be in the result object </span> <span>name: 'url', </span> <span>// The prompt message shown to the user </span> <span>description: 'Enter a URL', </span> <span>// Whether or not the user is required to enter a value </span> <span>required: true, </span> <span>// Validates the user input </span> <span>conform: function (value) { </span> <span>// In this case, the user must enter a valid URL </span> <span>return validUrl.isWebUri(value); </span> <span>} </span> <span>}], function (err<span>, result</span>) { </span> <span>// Perform some action following successful input </span> <span>performAction(phantomInstance, result.url); </span> <span>}); </span> <span>break; </span><span>} </span>在这一点上,我们已经定义了一个基本路径,可以通过该路径指定执行操作,并添加了一个提示以接受URL。我们只需要添加一个模块来处理该操作的逻辑即可。我们可以通过将一个名为hello_world.js的文件添加到操作目录中来做到这一点:
>
如您所见,该模块期望提供一个phantomjs对象(Phantominstance)和URL(URL)的实例。我们将暂时地定义Phantomjs实例的细节,但是目前足以看到我们为触发特定动作奠定了基础。既然我们已经制定了一定的惯例,我们可以轻松地以定义和理智的方式添加新的动作。<span>'use strict'; </span> <span>/** </span><span> * <span>@param Horseman phantomInstance </span></span><span> * <span>@param string url </span></span><span> */ </span>module<span>.exports = function (phantomInstance<span>, url</span>) { </span> <span>if (!url || typeof url !== 'string') { </span> <span>throw 'You must specify a url to ping'; </span> <span>} else { </span> <span>console.log('Pinging url: ', url); </span> <span>} </span> phantomInstance <span>.open(url) </span> <span>.status() </span> <span>.then(function (statusCode) { </span> <span>if (Number(statusCode) >= 400) { </span> <span>throw 'Page failed with status: ' + statusCode; </span> <span>} else { </span> <span>console.log('Hello world. Status code returned: ', statusCode); </span> <span>} </span> <span>}) </span> <span>.catch(function (err) { </span> <span>console.log('Error: ', err); </span> <span>}) </span> <span>// Always close the Horseman instance </span> <span>// Otherwise you might end up with orphaned phantom processes </span> <span>.close(); </span><span>}; </span>> 使用骑兵
爬行
>每次我们通过CLI框架触发操作时,我们的输入脚本(RUN.JS)实例化骑士实例并将其传递到指定的操作模块。在伪代码中,它看起来像这样:
>
现在,当我们运行命令时,骑手实例和输入URL将传递到Hello_world模块,导致Phantomjs请求URL,捕获其状态代码并将状态打印到控制台。我们刚刚使用骑马者进行了第一个真正的善意爬行。 giddyup!
<span>var phantomInstance = new Horseman({ </span> <span>phantomPath: '/usr/local/bin/phantomjs', </span> <span>loadImages: true, </span> <span>injectJquery: true, </span> <span>webSecurity: true, </span> <span>ignoreSSLErrors: true </span><span>}); </span> <span>performAction(phantomInstance, ...); </span>
复合互动的骑士方法
到目前为止,我们已经研究了非常简单的骑士用法,但是当我们将其方法链接在一起以在浏览器中执行一系列操作时,包装可以做得更多。为了演示其中一些功能,让我们定义一个动作,该操作模拟了通过GitHub导航以创建新存储库的用户。
请注意:此示例纯粹是出于演示目的,不应被视为创建GitHub存储库的可行方法。这仅仅是一个人如何使用骑手与Web应用程序进行交互的示例。如果您有兴趣以自动方式创建存储库,则应使用官方的GitHub API。
让我们假设新的爬网会像这样触发:>按照我们已经制定的CLI框架的约定,我们需要在名为create_repo.js的操作目录中添加一个新模块。与我们以前的“ Hello World”示例一样,create_repo模块导出一个包含该动作的所有逻辑的单个函数。
$ <span>node run.js -x hello_world </span>
请注意,在此操作中,我们将更多的参数传递给导出的函数,而不是以前。这些参数包括用户名,密码和存储库。一旦用户成功完成了及时挑战,我们将从run.js传递这些值。
program <span>.version('1.0.0') </span> <span>.option('-x --action-to-perform [string]', 'The type of action to perform.') </span> <span>.option('-u --url [string]', 'Optional URL used by certain actions') </span> <span>.parse(process.argv); </span>>在发生任何事情之前,我们必须添加逻辑。我们通过将案例添加到我们的主开关语句中来做到这一点:
>现在我们将此挂钩添加到run.js,当用户输入相关数据时,它将传递给操作,从而使我们可以继续进行爬网。
至于Create_repo爬网逻辑本身,我们使用骑手的方法来导航到GitHub登录页面,输入提供的用户名和密码,然后提交表单:<span>var performAction = require('./actions/' + program.actionToPerform) </span> <span>switch (program.actionToPerform) { </span> <span>case 'hello_world': </span> prompt<span>.get([{ </span> <span>// What the property name should be in the result object </span> <span>name: 'url', </span> <span>// The prompt message shown to the user </span> <span>description: 'Enter a URL', </span> <span>// Whether or not the user is required to enter a value </span> <span>required: true, </span> <span>// Validates the user input </span> <span>conform: function (value) { </span> <span>// In this case, the user must enter a valid URL </span> <span>return validUrl.isWebUri(value); </span> <span>} </span> <span>}], function (err<span>, result</span>) { </span> <span>// Perform some action following successful input </span> <span>performAction(phantomInstance, result.url); </span> <span>}); </span> <span>break; </span><span>} </span>
我们通过等待表单提交页面加载来继续链条:
之后,我们使用jQuery来确定登录是否成功:
<span>'use strict'; </span> <span>/** </span><span> * <span>@param Horseman phantomInstance </span></span><span> * <span>@param string url </span></span><span> */ </span>module<span>.exports = function (phantomInstance<span>, url</span>) { </span> <span>if (!url || typeof url !== 'string') { </span> <span>throw 'You must specify a url to ping'; </span> <span>} else { </span> <span>console.log('Pinging url: ', url); </span> <span>} </span> phantomInstance <span>.open(url) </span> <span>.status() </span> <span>.then(function (statusCode) { </span> <span>if (Number(statusCode) >= 400) { </span> <span>throw 'Page failed with status: ' + statusCode; </span> <span>} else { </span> <span>console.log('Hello world. Status code returned: ', statusCode); </span> <span>} </span> <span>}) </span> <span>.catch(function (err) { </span> <span>console.log('Error: ', err); </span> <span>}) </span> <span>// Always close the Horseman instance </span> <span>// Otherwise you might end up with orphaned phantom processes </span> <span>.close(); </span><span>}; </span>
>在我们的个人资料页面上,我们将导航到我们的存储库标签:
<span>var phantomInstance = new Horseman({ </span> <span>phantomPath: '/usr/local/bin/phantomjs', </span> <span>loadImages: true, </span> <span>injectJquery: true, </span> <span>webSecurity: true, </span> <span>ignoreSSLErrors: true </span><span>}); </span> <span>performAction(phantomInstance, ...); </span>
在我们的存储库选项卡时,我们检查是否已经存在带有指定名称的存储库。如果是这样,那么我们会丢下错误。如果不是,那么我们继续我们的顺序:
$ <span>node run.js -x create_repo </span>
假设没有错误,我们通过编程单击“新存储库”按钮并等待下一页:
module<span>.exports = function (phantomInstance<span>, username, password, repository</span>) { </span> <span>if (!username || !password || !repository) { </span> <span>throw 'You must specify login credentials and a repository name'; </span> <span>} </span> <span>... </span><span>} </span>
之后,我们输入提供的存储库名称并提交表格:
<span>switch (program.actionToPerform) { </span> <span>case 'create_repo': </span> prompt<span>.get([{ </span> <span>name: 'repository', </span> <span>description: 'Enter repository name', </span> <span>required: true </span> <span>}, { </span> <span>name: 'username', </span> <span>description: 'Enter GitHub username', </span> <span>required: true </span> <span>}, { </span> <span>name: 'password', </span> <span>description: 'Enter GitHub password', </span> <span>hidden: true, </span> <span>required: true </span> <span>}], function (err<span>, result</span>) { </span> <span>performAction( </span> phantomInstance<span>, </span> result<span>.username, </span> result<span>.password, </span> result<span>.repository </span> <span>); </span> <span>}); </span> <span>break; </span> <span>... </span>>一旦到达生成页面,我们就会知道存储库是创建的:
与任何骑马爬行一样,至关重要的是,我们结束了骑马的实例:
phantomInstance <span>.open('https://github.com/login') </span> <span>.type('input[name="login"]', username) </span> <span>.type('input[name="password"]', password) </span> <span>.click('input[name="commit"]') </span>
>未能关闭骑士实例可能会导致机器上的孤立phantomjs处理。
<span>.waitForNextPage() </span>>爬行以收集数据
在这一点上,我们已经组装了一系列静态序列,以编程方式在GitHub上创建一个新的存储库。为此,我们链接了一系列的骑手方法。
这种方法对于事先已知的特定结构和行为模式可能很有用,但是,您可能会发现您需要在某个时候实现更灵活的脚本。如果您的动作序列有可能根据上下文变化或产生多个不同的结果,则可能是这种情况。如果您需要从DOM中提取数据,也将是这种情况。
在这种情况下,您可以使用Horseman的evaliate()方法,它允许您通过注入内联或外部链接JavaScript来执行浏览器中的自由形式交互。>
>本节演示了从页面中提取基本数据的示例(在这种情况下,锚点链接)。可能需要这种情况的一种情况是构建一个污损检测轨,以击中域上的每个URL。与我们的最后一个示例一样,我们必须首先在操作目录中添加一个新模块:
,然后在run.js中为新操作添加一个钩子:
$ <span>node run.js -x hello_world </span>>
现在,此代码已经到位,我们可以通过运行以下命令来从任何给定的页面提取链接:
program <span>.version('1.0.0') </span> <span>.option('-x --action-to-perform [string]', 'The type of action to perform.') </span> <span>.option('-u --url [string]', 'Optional URL used by certain actions') </span> <span>.parse(process.argv); </span>
>此操作演示了从页面上提取数据,并且不会利用骑手内置的任何浏览器操作。它直接执行您在estuation()方法中放置的任何JavaScript,并且会像在浏览器环境中本地运行一样。
><span>var performAction = require('./actions/' + program.actionToPerform) </span> <span>switch (program.actionToPerform) { </span> <span>case 'hello_world': </span> prompt<span>.get([{ </span> <span>// What the property name should be in the result object </span> <span>name: 'url', </span> <span>// The prompt message shown to the user </span> <span>description: 'Enter a URL', </span> <span>// Whether or not the user is required to enter a value </span> <span>required: true, </span> <span>// Validates the user input </span> <span>conform: function (value) { </span> <span>// In this case, the user must enter a valid URL </span> <span>return validUrl.isWebUri(value); </span> <span>} </span> <span>}], function (err<span>, result</span>) { </span> <span>// Perform some action following successful input </span> <span>performAction(phantomInstance, result.url); </span> <span>}); </span> <span>break; </span><span>} </span>>在本节中应注意的最后一件事,该部分提到了较早的提及:不仅可以使用estaution()方法在浏览器中执行自定义JavaScript,而且还可以在运行之前将外部脚本注入运行时环境您的评估逻辑。可以这样做:
>通过扩展上面的逻辑,您几乎可以在任何网站上执行任何操作。
><span>'use strict'; </span> <span>/** </span><span> * <span>@param Horseman phantomInstance </span></span><span> * <span>@param string url </span></span><span> */ </span>module<span>.exports = function (phantomInstance<span>, url</span>) { </span> <span>if (!url || typeof url !== 'string') { </span> <span>throw 'You must specify a url to ping'; </span> <span>} else { </span> <span>console.log('Pinging url: ', url); </span> <span>} </span> phantomInstance <span>.open(url) </span> <span>.status() </span> <span>.then(function (statusCode) { </span> <span>if (Number(statusCode) >= 400) { </span> <span>throw 'Page failed with status: ' + statusCode; </span> <span>} else { </span> <span>console.log('Hello world. Status code returned: ', statusCode); </span> <span>} </span> <span>}) </span> <span>.catch(function (err) { </span> <span>console.log('Error: ', err); </span> <span>}) </span> <span>// Always close the Horseman instance </span> <span>// Otherwise you might end up with orphaned phantom processes </span> <span>.close(); </span><span>}; </span>使用骑手屏幕截图
>我想证明的最终用例是您将如何使用Horseman拍摄屏幕截图。我们可以使用Horseman的ScreenShotBase64()方法来完成此操作,该方法返回代表屏幕截图的base64编码字符串。
与我们上一个示例一样,我们必须首先在操作目录中添加一个新模块:
,然后在run.js中为新操作添加一个钩子:
>
<span>var phantomInstance = new Horseman({ </span> <span>phantomPath: '/usr/local/bin/phantomjs', </span> <span>loadImages: true, </span> <span>injectJquery: true, </span> <span>webSecurity: true, </span> <span>ignoreSSLErrors: true </span><span>}); </span> <span>performAction(phantomInstance, ...); </span>现在,您可以使用以下命令进行屏幕截图:
>
$ <span>node run.js -x create_repo </span>>使用base64编码字符串的原因(例如,保存实际图像)是它们是表示原始图像数据的便捷方法。这个堆叠式的答案更详细。
>
如果要保存实际映像,则使用屏幕截图()方法。module<span>.exports = function (phantomInstance<span>, username, password, repository</span>) { </span> <span>if (!username || !password || !repository) { </span> <span>throw 'You must specify login credentials and a repository name'; </span> <span>} </span> <span>... </span><span>} </span>>
结论
本教程试图展示自定义的CLI微框架和一些基本的逻辑,用于使用Horseman软件包来利用Phantomjs,以爬Node.js爬网。虽然使用CLI框架可能会使许多项目受益,但爬行通常仅限于非常特定的问题域。一个共同的领域是质量保证(QA),可以将爬网用于功能和用户界面测试。另一个领域是安全性,例如,您可能想定期爬网,以检测到它是否已被污损或折衷。
>无论您的项目可能是什么情况,请确保清楚地定义您的目标并尽可能不引人注目。在可能的情况下获得许可,请在最大程度上礼貌,并注意永远不要DDOS。如果您怀疑自己正在产生大量的自动流量,那么您可能会重新评估您的目标,实施或许可水平。
经常询问的问题(常见问题解答)有关网络爬行的节点和phantomjs骑手Web爬网和Web刮擦之间有什么区别?
Web爬网和Web刮擦是两个不同的过程,尽管它们通常可以互换使用。网络爬行是系统浏览网络的过程,通常由机器人或蜘蛛进行。它涉及索引网站的内容和以下链接到其他网页。另一方面,网络刮擦是从网站提取特定数据的过程。它涉及解析网页的HTML以删除所需的数据。虽然网络爬网是关于导航和索引的,但网络刮擦是关于数据提取的。
异步性质。它允许并发处理,这意味着您可以同时爬网多页。这使其比同步执行的其他语言要快得多。此外,Node.js拥有一个丰富的生态系统,具有许多可以帮助网络爬行的库和工具,例如Phantomjs Horseman。 > Phantomjs Horseman是一个Node.js软件包,可为使用Phantomjs自动化Web浏览器提供高级API。它允许您在网页上执行操作,例如单击链接,填写表单和屏幕截图。这使其成为网络爬网的强大工具,因为它使您可以像人类用户一样与网页进行交互。
> JavaScript渲染如何影响Web爬行?>>我可以使用Web爬网来监视网站上的更改吗? ,网络爬行可用于监视网站上的更改。通过定期爬行网站并将当前状态与以前的状态进行比较,您可以检测任何更改。这对于各种目的可能很有用,例如在电子商务网站上跟踪价格变化或监视新闻网站上的更新。
网络爬行法律?
>>网络爬行的合法性取决于在包括您所处的管辖权以及您爬行的特定网站上的几个因素上。一些网站明确允许Web在其robots.txt文件中爬行,而另一些网站则禁止Web爬网。重要的是要尊重网站的robots.txt文件,并且不要在短时间内用太多请求超载网站的服务器。>
>我如何优化我的网络爬行过程?是优化网络爬行过程的几种方法。一种方法是使用广度优先搜索(BFS)算法,该算法可确保您在进入下一个深度级别之前,在一定深度爬网。另一种方法是根据页面的相关性优先考虑爬网。例如,如果您要抓取电子商务网站,您可能想在博客文章之前爬网。 >是的,使用Phantomjs Horseman,您可以自动登录网站的过程。这使您可以在登录后访问仅访问的页面。但是,您应该意识到这可能违反网站的服务条款。我如何处理网络爬网中的动态内容?>处理动态内容在Web Crawling中可能具有挑战性,作为传统Web爬网仅解析网页的静态HTML。但是,使用Phantomjs Horseman之类的工具,您可以像人类用户一样渲染JavaScript并与动态内容进行交互。这使您可以从严重依赖JavaScript进行内容生成的网站上爬网和提取数据。>>如何阻止我的网络爬行者被阻塞?一种方法是尊重网站的robots.txt文件,该文件提供了有关您允许爬网的哪些部分的指南。另一种方法是限制您将请求发送到网站的速率,以避免服务器超载。您也可以旋转IP地址和用户代理以避免被检测为机器人。>
>我可以使用Web爬网来监视网站上的更改吗? ,网络爬行可用于监视网站上的更改。通过定期爬行网站并将当前状态与以前的状态进行比较,您可以检测任何更改。这对于各种目的可能很有用,例如在电子商务网站上跟踪价格变化或监视新闻网站上的更新。
网络爬行法律?
>>网络爬行的合法性取决于在包括您所处的管辖权以及您爬行的特定网站上的几个因素上。一些网站明确允许Web在其robots.txt文件中爬行,而另一些网站则禁止Web爬网。重要的是要尊重网站的robots.txt文件,并且不要在短时间内用太多请求超载网站的服务器。>
>我如何优化我的网络爬行过程?是优化网络爬行过程的几种方法。一种方法是使用广度优先搜索(BFS)算法,该算法可确保您在进入下一个深度级别之前,在一定深度爬网。另一种方法是根据页面的相关性优先考虑爬网。例如,如果您要抓取电子商务网站,您可能想在博客文章之前爬网。 >是的,使用Phantomjs Horseman,您可以自动登录网站的过程。这使您可以在登录后访问仅访问的页面。但是,您应该意识到这可能违反网站的服务条款。我如何处理网络爬网中的动态内容?>处理动态内容在Web Crawling中可能具有挑战性,作为传统Web爬网仅解析网页的静态HTML。但是,使用Phantomjs Horseman之类的工具,您可以像人类用户一样渲染JavaScript并与动态内容进行交互。这使您可以从严重依赖JavaScript进行内容生成的网站上爬网和提取数据。>>如何阻止我的网络爬行者被阻塞?一种方法是尊重网站的robots.txt文件,该文件提供了有关您允许爬网的哪些部分的指南。另一种方法是限制您将请求发送到网站的速率,以避免服务器超载。您也可以旋转IP地址和用户代理以避免被检测为机器人。>
>如何阻止我的网络爬行者被阻塞?一种方法是尊重网站的robots.txt文件,该文件提供了有关您允许爬网的哪些部分的指南。另一种方法是限制您将请求发送到网站的速率,以避免服务器超载。您也可以旋转IP地址和用户代理以避免被检测为机器人。>
以上是网络与节点,phantomjs和骑手一起爬行的详细内容。更多信息请关注PHP中文网其他相关文章!

JavaScript核心数据类型在浏览器和Node.js中一致,但处理方式和额外类型有所不同。1)全局对象在浏览器中为window,在Node.js中为global。2)Node.js独有Buffer对象,用于处理二进制数据。3)性能和时间处理在两者间也有差异,需根据环境调整代码。

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

SublimeText3汉化版
中文版,非常好用