【问题标题】:is it possible to write web crawler in javascript?是否可以用 javascript 编写网络爬虫?
【发布时间】:2012-06-18 13:04:10
【问题描述】:

我想爬取页面并检查相应页面中的超链接,并跟踪这些超链接并从页面中捕获数据

【问题讨论】:

  • 对于新访问者(2017 年之后)-> 从 Google 查看有关 Puppeteer 的答案

标签: javascript web-crawler


【解决方案1】:

一般来说,浏览器 JavaScript 只能在其源域内进行爬取,因为获取页面将通过 Ajax 完成,而这受到 Same-Origin Policy 的限制。

如果运行爬虫脚本的页面位于 www.example.com 上,则该脚本可以爬取 www.example.com 上的所有页面,但不能爬取任何其他来源的页面(除非一些边缘情况适用,例如,Access-Control-Allow-Origin 标头是为另一台服务器上的页面设置的)。

如果你真的想在浏览器JS中编写一个功能齐全的爬虫,你可以编写一个浏览器扩展:例如,Chrome extensions是打包的Web应用程序以特殊权限运行,包括@987654325 @。这种方法的困难在于,如果要支持多个浏览器,就必须编写多个版本的爬虫。 (如果爬虫只是供个人使用,那可能不是问题。)

【讨论】:

  • 大多数现代浏览器都支持用 Javascript 编写的扩展程序,而不仅仅是 Chrome - 我想知道您为什么只在回答中提到 Chrome?
  • @lucideer 一个公平的问题——我最初写了一个稍微好一点的解释,但认为它太啰嗦了。我已经编辑了我的最后一段,使其更清晰。
  • 对描述浏览器环境的限制并完成之前的答案投赞成票。
【解决方案2】:

如果您使用服务器端 javascript,这是可能的。 你应该看看 node.js

并且可以在下面的链接中找到爬虫的示例:

http://www.colourcoding.net/blog/archive/2010/11/20/a-node.js-web-spider.aspx

【讨论】:

  • 不需要是服务器端;它根本不需要是一个网络应用程序(如果你使用节点)。
  • 确实,但我喜欢认为节点主要处理业务逻辑,所以我认为应该归类为服务器端逻辑。
  • 你可以在node中编写命令行应用程序,一个命令行应用程序就可以满足问题中的要求。它不会是服务器端,因为它不会是一个 Web 应用程序(所以没有服务器端)。
  • 我已经使用.net 构建了爬虫只是想知道在.net 平台上运行的爬虫是否会产生一些与跟踪IP 地址等相关的问题?
【解决方案3】:

我们可以借助无头 webkit 从服务器端使用 Javascript 抓取页面。对于爬虫,我们很少有像 PhantomJS、CasperJS 这样的库,还有一个新的 PhantomJS 包装器,称为 Nightmare JS,它使工作更容易。

【讨论】:

    【解决方案4】:

    Google's Chrome team has released puppeteer,2017 年 8 月,一个节点库,为无头和非无头 Chrome 提供高级 API(无头 Chrome 可用 since 59)。

    它使用 Chromium 的嵌入式版本,因此可以保证开箱即用。如果你想使用特定的 Chrome 版本,你可以通过启动 puppeteer 来实现,并以可执行路径作为参数,例如:

    const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});
    

    导航到网页并从中截取屏幕截图的示例显示了它是多么简单(取自 GitHub 页面):

    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();
    })();
    

    【讨论】:

    • 谢谢!这应该被检查为 2017 年的正确答案。:)
    【解决方案5】:

    有一些方法可以规避 JS 的同源策略。我为 facebook 编写了一个爬虫,它从我的朋友和我朋友的朋友的 facebook 个人资料中收集信息,并允许按性别、当前位置、年龄、军事状态(你明白我的意思)过滤结果。这很简单。我只是从控制台运行它。这样,您的脚本将获得在当前域上执行请求的特权。您还可以制作一个小书签来从您的书签中运行脚本。

    另一种方法是提供 PHP 代理。您的脚本将访问当前域上的代理并使用 PHP 从另一个请求文件。只是要小心那些。如果您不小心,这些可能会被第三方劫持并用作公共代理。

    祝你好运,也许你会像我一样在这个过程中结交一两个朋友 :-)

    【讨论】:

      【解决方案6】:

      我的典型设置是使用带有跨域权限集的浏览器扩展,它同时注入爬虫代码和 jQuery。

      对 Javascript 爬虫的另一种看法是使用无头浏览器,如 phantomJS 或 casperJS(增强 phantom 的能力)

      【讨论】:

        【解决方案7】:

        这就是你需要的http://zugravu.com/products/web-crawler-spider-scraping-javascript-regular-expression-nodejs-mongodb 他们使用 NodeJS、MongoDB 和 ExtJs 作为 GUI

        【讨论】:

        • 尝试在您的答案中引用链接中的一些要点。这样,如果网站出现故障或内容在没有适当重定向的情况下移动到不同的 URL,那么您的回答仍然会有所帮助。
        【解决方案8】:

        是的,有可能

        1. 使用 NODEJS(它的服务器端 JS)
        2. nodeJS 中有 NPM(处理 3rd 方模块的包管理器)
        3. 在NodeJS中使用PhantomJS(可以爬取网站的第三方模块是PhantomJS)

        【讨论】:

          【解决方案9】:

          对此有一种客户端方法,使用 Firefox Greasemonkey 扩展。使用 Greasemonkey,您可以创建每次打开指定 url 时要执行的脚本。

          这里是一个例子:

          如果你有这样的网址:

          http://www.example.com/products/pages/1

          http://www.example.com/products/pages/2

          然后你可以使用这样的东西来打开所有包含产品列表的页面(手动执行)

          var j = 0;
          for(var i=1;i<5;i++)
          { 
            setTimeout(function(){
            j = j + 1;
            window.open('http://www.example.com/products/pages/ + j, '_blank');
          
          }, 15000 * i);
          

          }

          然后您可以创建一个脚本以在每个产品列表页面的新窗口中打开所有产品,并将此 URL 包含在 Greasemonkey 中。

          http://www.example.com/products/pages/*

          然后是每个产品页面的脚本来提取数据并调用webservice传递数据和关闭窗口等等。

          【讨论】:

            【解决方案10】:

            我在 github 上做了一个示例 javascript 爬虫。

            它是事件驱动的,并使用内存中的队列来存储所有资源(即 url)。

            如何在你的节点环境中使用

            var Crawler = require('../lib/crawler')
            var crawler = new Crawler('http://www.someUrl.com');
            
            // crawler.maxDepth = 4;
            // crawler.crawlInterval = 10;
            // crawler.maxListenerCurrency = 10;
            // crawler.redisQueue = true;
            crawler.start();
            

            这里我只是向你展示 2 个 javascript 爬虫的核心方法。

            Crawler.prototype.run = function() {
              var crawler = this;
              process.nextTick(() => {
                //the run loop
                crawler.crawlerIntervalId = setInterval(() => {
            
                  crawler.crawl();
            
                }, crawler.crawlInterval);
                //kick off first one
                crawler.crawl();
              });
            
              crawler.running = true;
              crawler.emit('start');
            }
            
            
            Crawler.prototype.crawl = function() {
              var crawler = this;
            
              if (crawler._openRequests >= crawler.maxListenerCurrency) return;
            
            
              //go get the item
              crawler.queue.oldestUnfetchedItem((err, queueItem, index) => {
                if (queueItem) {
                  //got the item start the fetch
                  crawler.fetchQueueItem(queueItem, index);
                } else if (crawler._openRequests === 0) {
                  crawler.queue.complete((err, completeCount) => {
                    if (err)
                      throw err;
                    crawler.queue.getLength((err, length) => {
                      if (err)
                        throw err;
                      if (length === completeCount) {
                        //no open Request, no unfetcheditem stop the crawler
                        crawler.emit("complete", completeCount);
                        clearInterval(crawler.crawlerIntervalId);
                        crawler.running = false;
                      }
                    });
                  });
                }
            
              });
            };
            

            这里是github链接https://github.com/bfwg/node-tinycrawler。 它是一个用 1000 行代码编写的 JavaScript 网络爬虫。 这应该会让你走上正轨。

            【讨论】:

              【解决方案11】:

              您可以创建一个从远程 json 文件驱动的网络爬虫,该文件会在每个选项卡加载后立即在新选项卡中打开页面中的所有链接,已打开的链接除外。如果您设置一个在基本浏览器中运行的浏览器扩展程序(除了 Web 浏览器和 Internet 配置程序之外什么都不运行),并将其运送并安装在具有良好 Internet 的地方,您可以使用旧计算机创建网页数据库。那只需要检索每个选项卡的内容。与大多数对搜索引擎成本的估计相反,你可以花大约 2000 美元来做到这一点。您只需要基本上让您的算法根据页面的 innerText 属性中出现的术语数量、关键字和描述来提供页面。您还可以设置另一台 PC 从一次性数据库中重新抓取旧页面并添加更多。我估计最多需要 3 个月和 20000 美元。

              【讨论】:

                【解决方案12】:

                Axios + Cheerio

                您可以使用 axios 和 Cheerios 来做到这一点。检查axios docs 的响应格式。

                const cheerio = require('cheerio');
                const axios = require('axios');
                //crawl
                //get url
                var url = 'http://amazon.com';
                
                axios.get(url)
                .then((res) => {
                
                //response format
                var body = res.data;
                var statusCode = res.status;
                var statusText =  res.statusText;
                var headers = res.headers;
                var request = res.request;
                var config = res.config;
                
                //jquery
                let $ = cheerio.load(body);
                
                //example
                
                //meta tags
                var title = $('meta[name=title]').attr('content');
                if(title == undefined || title == 'undefined'){
                title = $('title').text();
                }else{
                title = title;
                }
                var description = $('meta[name=description]').attr('content');
                var keywords = $('meta[name=keywords]').attr('content');
                var author = $('meta[name=author]').attr('content');
                var type = $('meta[http-equiv=content-type]').attr('content');
                var favicon = $('link[rel="shortcut icon"]').attr('href');
                
                
                }).catch(function (e) {
                console.log(e);
                });
                

                Node-Fetch + Cheerio

                您可以使用 node-fetch 和cheerio 做同样的事情。

                fetch(url, {
                method: "GET",
                }).then(function(response){
                
                //response
                var html = response.text();
                
                //return
                return html;
                
                })
                .then(function(res) {
                
                //response html    
                var html = res;
                
                //jquery
                let $ = cheerio.load(html);
                
                //meta tags
                var title = $('meta[name=title]').attr('content');
                if(title == undefined || title == 'undefined'){
                title = $('title').text();
                }else{
                title = title;
                }
                var description = $('meta[name=description]').attr('content');
                var keywords = $('meta[name=keywords]').attr('content');
                var author = $('meta[name=author]').attr('content');
                var type = $('meta[http-equiv=content-type]').attr('content');
                var favicon = $('link[rel="shortcut icon"]').attr('href');
                
                })
                .catch((error) => {
                
                console.error('Error:', error);
                
                });
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-06-19
                  • 2011-06-07
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-07-14
                  相关资源
                  最近更新 更多