如何使用nodejs做爬虫程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用nodejs做爬虫程序相关的知识,希望对你有一定的参考价值。

参考技术A

    目标

    抓取网站上的妹子照片。

    第三方模块

    superagent : 第三方Nodejs 模块,用于处理服务器和客户端的Http请求。

    cheerio : 为服务器端定制的Jquery实现。

    思路

    通过superagent 获取目标网站的dom

    通过cheerio对dom进行解析,获得通用布局。

    如果只是爬取一个页面,则可以直接将目标页面的目标元素获取

    如果是分页或者多个页面,可以通过循环获得目标链接,进行多次抓取。

    实现

    这里我们实现一个抓取网站妹子的照片。

    目标网址:http://jandan.net/ooxx/ (对于该网站,并没有恶意攻击的意思.)

    代码如下:

//引入第三方和通用模块
var fs = require('fs');//为了将抓取的图片存到本地,使用fs
var superagent = require('superagent');//引入superagent
var cheerio = require('cheerio');//引入jquery实现
 
var filePath = '/node/学习/sis/img/';//定义抓取妹子文件存放路径
var count = 0;//记录抓取数量
var test = [];
//抓取一个页面的实现。
var getOnePage = function(url)
    //因为煎蛋对请求做了限制,所以将cookie加上了。如果你要访问该网站的话,可以通过<a href="https://www.baidu.com/s?wd=%E6%B5%8F%E8%A7%88%E5%99%A8&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y3uAndPH6zm1I9PjPhuhRz0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6KdThsqpZwYTjCEQLGCpyw9Uz4Bmy-bIi4WUvYETgN-TLwGUv3EPjRLP1msP1TzPjTYnj0vnjfd" target="_blank" class="baidu-highlight">浏览器</a>查找cookie 并进行替换
    superagent.get(url)
    .set(
            'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/47.0.2526.111 Safari/537.36'
    )
    .set('cookie','500322148=53; Hm_lvt_fd93b7fb546adcfbcf80c4fc2b54da2c=1454117846; Hm_lpvt_fd93b7fb546adcfbcf80c4fc2b54da2c=1454119909')
    .set(
        'accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'connection' : 'keep-alive',
        'host' : 'jandan.net'
    )
    .end(function(err,sres)//这里是对获取的dom进行处理
        if(err)throw err;
        var $ = cheerio.load(sres.text);
        var nextUrl = $('.previous-comment-page').attr('href');//获得下一页的链接,为了开始下一次请求
        $('img').each(function(index,ele)//循环该页面的所有图片并得到对应的链接,放进数组。
            var u = '';
            if($(ele).attr('org_src'))
                u = $(ele).attr('org_src');
            else
                u = $(ele).attr('src');    
            
            test.push(u);
            //通过superagent 获取图片数据,并保存到本地。
            superagent.get(u).end(function(err,sres)
                if(err)throw err;
                //根据访问路径获得文件名称
                var ttt = u.split('/');
                var name = ttt[ttt.length-1];
                var path = filePath+name
                fs.writeFile(path,sres.body,function()
                    count++;
                    console.log(u);
                    console.log('已成功抓取..'+count+'张');
                );
            );
        );
        if(null != nextUrl && '' != nextUrl) //何时开始下一次请求
            getOnePage(nextUrl);
        
    ); 
 
;
 
getOnePage('http://jandan.net/ooxx/');//触发第一次请求开始

本回答被提问者采纳

如何使用 NodeJS 在本地测试 AWS Lambda 处理程序?

【中文标题】如何使用 NodeJS 在本地测试 AWS Lambda 处理程序?【英文标题】:How to test AWS Lambda handler locally using NodeJS? 【发布时间】:2019-01-31 19:05:07 【问题描述】:

我正在按照these 的说明创建一个在 Lambda 中执行的基本网络爬虫。我有编写 selenium 代码的经验,但没有使用 Node JS。我让项目在 Lambda 中运行,但是当我尝试在本地编辑项目以执行我想要的 selenium 代码时,它不起作用。当我运行node index.js 时,exports.handler 中的任何内容都不会被执行。我将如何在本地执行这个项目?谢谢!

【问题讨论】:

您需要致电您的function,而不仅仅是导出声明。导入您导出的handler.js 分配给index.js 中的变量并调用您的函数。 (假设exports.handlerfunction。) 【参考方案1】:

这就是我所做的:

index.js

exports.handler = async (event) => 
    console.log('hello world');

    const response = 
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!')
    ;

    return response;
;

package.json

"scripts": 
  "locally": "node -e \"console.log(require('./index').handler(require('./event.json')));\""

event.json


  "Records": [
    
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "eu-central-1",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": 
        "principalId": "AIDAJDPLRKLG7UEXAMPLE"
      ,
      "requestParameters": 
        "sourceIPAddress": "127.0.0.1"
      ,
      "responseElements": 
        "x-amz-request-id": "C3D13FE58DE4C810",
        "x-amz-id-2": "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"
      ,
      "s3": 
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigRule",
        "bucket": 
          "name": "my-bucket",
          "ownerIdentity": 
            "principalId": "A3NL1KOZZKExample"
          ,
          "arn": "arn:aws:s3:::my-bucket"
        ,
        "object": 
          "key": "HelloWorld.jpg",
          "size": 1024,
          "eTag": "d41d8cd98f00b204e9800998ecf8427e",
          "versionId": "096fKKXTRTtl3on89fVO.nfljtsv6qko"
        
      
    
  ]

壳牌

npm run locally

输出

> node -e "console.log(require('./index').handler());"

hello world
Promise   statusCode: 200, body: '"Hello from Lambda!"'  

【讨论】:

为什么需要额外的npm 步骤?只运行 node 命令更直接,对吧? 不需要额外的 npm 步骤。这对我来说只是一种方便,因为我可以在调用中添加特定于该代码库的参数。坦率地说,我更容易记住:) 在这种情况下我们如何传递事件? 我喜欢方便。但是,如果您想针对您的 lambda 函数运行 10 个不同的测试场景怎么办?你如何传递不同的事件变体——快乐路径、悲伤路径、空事件、无效数据等? 您可以创建一个名为 sad-event.json 的新 json 文件,并需要该文件而不是“./event.json”。您可以将它们组织在一个名为 test-events 的文件夹中,因此您的路径可以是“test-events/happy.json”【参考方案2】:

您需要从另一个文件调用您的处理程序函数,比如说testHandler.js,以便通过 NodeJs 运行。

这将像这样完成

//import your handler file or main file of Lambda
let handler = require('./handler');

//Call your exports function with required params
//In AWS lambda these are event, content, and callback
//event and content are JSON object and callback is a function
//In my example i'm using empty JSON
handler.handlerEvent( , //event
    , //content
    function(data,ss)   //callback function with two arguments 
        console.log(data);
    );

现在您可以使用node testHandler.js 来测试您的处理函数。

编辑:示例事件和内容数据按要求

事件:


    "resource": "/API/PATH",
    "path": "/API/PATH",
    "httpMethod": "POST",
    "headers": 
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate, br",
        "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
        "cache-control": "no-cache",
        "CloudFront-Forwarded-Proto": "https",
        "CloudFront-Is-Desktop-Viewer": "true",
        "CloudFront-Is-Mobile-Viewer": "false",
        "CloudFront-Is-SmartTV-Viewer": "false",
        "CloudFront-Is-Tablet-Viewer": "false",
        "CloudFront-Viewer-Country": "IN",
        "content-type": "application/json",
        "Host": "url.us-east-1.amazonaws.com",
        "origin": "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop",
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
        "Via": "2.0 XXXXXXXXXXXXXX.cloudfront.net (CloudFront)",
        "X-Amz-Cf-Id": "XXXXXXXXXX51YYoOl75RKjAWEhCyna-fuQqEBjSL96TMkFX4H0xaZQ==",
        "X-Amzn-Trace-Id": "Root=1-XXX03c23-25XXXXXX948c8fba065caab5",
        "x-api-key": "SECUREKEY",
        "X-Forwarded-For": "XX.XX.XXX.XXX, XX.XXX.XX.XXX",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https"
    ,
    "multiValueHeaders": 
        "Accept": [ "*/*" ],
        "Accept-Encoding": [ "gzip, deflate, br" ],
        "Accept-Language": [ "en-GB,en-US;q=0.9,en;q=0.8" ],
        "cache-control": [ "no-cache" ],
        "CloudFront-Forwarded-Proto": [ "https" ],
        "CloudFront-Is-Desktop-Viewer": [ "true" ],
        "CloudFront-Is-Mobile-Viewer": [ "false" ],
        "CloudFront-Is-SmartTV-Viewer": [ "false" ],
        "CloudFront-Is-Tablet-Viewer": [ "false" ],
        "CloudFront-Viewer-Country": [ "IN" ],
        "content-type": [ "application/json" ],
        "Host": [ "apiurl.us-east-1.amazonaws.com" ],
        "origin": [ "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop" ],
        "User-Agent": [ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" ],
        "Via": [ "2.0 XXXXXXXXXXXXXX.cloudfront.net (CloudFront)" ],
        "X-Amz-Cf-Id": [ "XXXXXXXXXhCyna-fuQqEBjSL96TMkFX4H0xaZQ==" ],
        "X-Amzn-Trace-Id": [ "Root=1-XXXXXXX67339948c8fba065caab5" ],
        "x-api-key": [ "SECUREAPIKEYPROVIDEDBYAWS" ],
        "X-Forwarded-For": [ "xx.xx.xx.xxx, xx.xxx.xx.xxx" ],
        "X-Forwarded-Port": [ "443" ],
        "X-Forwarded-Proto": [ "https" ]
    ,
    "queryStringParameters": null,
    "multiValueQueryStringParameters": null,
    "pathParameters": null,
    "stageVariables": null,
    "requestContext": 
        "resourceId": "xxxxx",
        "resourcePath": "/api/endpoint",
        "httpMethod": "POST",
        "extendedRequestId": "xxXXxxXXw=",
        "requestTime": "29/Nov/2018:19:21:07 +0000",
        "path": "/env/api/endpoint",
        "accountId": "XXXXXX",
        "protocol": "HTTP/1.1",
        "stage": "env",
        "domainPrefix": "xxxxx",
        "requestTimeEpoch": 1543519267874,
        "requestId": "xxxxxxx-XXXX-xxxx-86a8-xxxxxa",
        "identity": 
            "cognitoIdentityPoolId": null,
            "cognitoIdentityId": null,
            "apiKey": "SECUREAPIKEYPROVIDEDBYAWS",
            "cognitoAuthenticationType": null,
            "userArn": null,
            "apiKeyId": "xxXXXXxxxxxx",
            "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
            "accountId": null,
            "caller": null,
            "sourceIp": "xx.xxx.xxx.xxx",
            "accessKey": null,
            "cognitoAuthenticationProvider": null,
            "user": null
        ,
        "domainName": "url.us-east-1.amazonaws.com",
        "apiId": "xxxxx"
    ,
    "body": "\n    \"city\": \"Test 1 City\",\n    \"state\": \"NY\",\n    \"zipCode\": \"11549\"\n",
    "isBase64Encoded": false

内容:


    "callbackWaitsForEmptyEventLoop": true,
    "logGroupName": "/aws/lambda/lambda-name",
    "logStreamName": "2018/11/29/[$LATEST]xxxxxxxxxxxb",
    "functionName": "lambda-name",
    "memoryLimitInMB": "1024",
    "functionVersion": "$LATEST",
    "invokeid": "xxxxx-xxx-11e8-xxx-xxxxxxxf9",
    "awsRequestId": "xxxxxx-xxxxx-11e8-xxxx-xxxxxxxxx",
    "invokedFunctionArn": "arn:aws:lambda:us-east-1:xxxxxxxx:function:lambda-name"

【讨论】:

您能否举例说明在 AWS Lambda 上调用 event 时通常的样子? @PetrusTheron 添加了示例事件和内容。 事件看起来不同,具体取决于事件的触发器。在编辑 lambda 的 Web UI 中,测试事件选择下拉列表将“配置测试事件”作为选项之一。在那里,他们为所有类型的触发器提供原型事件。【参考方案3】:

在您的index.js 中,刚刚定义并导出了一个处理函数,但没有人调用它。在 Lambda 环境中,一些 AWS 代码将使用消息调用此处理程序。在您的本地环境中,您必须自己调用您的处理程序。

你也可以看看this doc,这是一种在本地环境中“模拟”Lambda的方法。

【讨论】:

【参考方案4】:

您可以查看lambda-local。这比上面接受的答案要花哨一些。例如,它支持传递环境变量并为您的负载使用 JSON 文件。

【讨论】:

【参考方案5】:

如果你只想在本地执行它,你可以使用官方的sam cli 工具 https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-local-invoke.html

如果你使用 VSCode,你也可以查看这个扩展:

https://marketplace.visualstudio.com/items?itemName=bogdan-onu.invoke

【讨论】:

【参考方案6】:

经过一些测试(使用 Node 14.17.3),这可能是最简单的入门方法

let handler = require('./index.js');

handler.handler ( 
  , // event
  , // content 
  (error, result) =>  
     if (error) console.error(JSON.stringify(error, null, 2));
     else console.log(JSON.stringify(result, null, 2));
  
);

【讨论】:

以上是关于如何使用nodejs做爬虫程序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用nodejs做爬虫程序

如何使用nodejs做爬虫程序

如何使用nodejs做爬虫程序

如何使用nodejs做爬虫程序

如何用nodejs开发爬虫程序?

如何使用 NodeJS 在本地测试 AWS Lambda 处理程序?