Node.js,Tor,Puppeteer和Cheerio:匿名网络抓取

Web抓取是一种从网站收集数据的方法。该术语通常用于自动数据收集。今天,我们将讨论如何匿名从网站收集数据。有人在Web抓取中希望匿名的原因是,因为许多Web服务器将某些规则应用于IP地址的连接,在一定的时间内从中发出一定数量的请求。在这里,我们将使用以下工具:

  • 木偶 -用于访问网页。
  • Cheerio-用于解析HTML代码。
  • Tor-从不同的IP地址执行每个请求。

应该注意的是,网络抓取的法律方面是一个复杂且常常不清楚的问题。因此,请遵守所收集数据页面的“ 使用条款 ”。这是有关此主题的一些好材料。



Tor安装


让我们从头开始-因此,首先,使用以下命令安装Tor客户端:

sudo apt-get install tor

Tor设置


现在配置Tor客户端。Tor的默认配置使用SOCKS端口,该端口为我们提供了到单个输出节点的一条路径(即一个IP地址)。对于Tor的日常使用(例如仅浏览网络),这是非常合适的。但是我们需要一些IP地址。这将允许您在网络抓取过程中在它们之间切换。

为了根据需要配置Tor,我们只需打开其他端口即可侦听SOCKS连接。这可以通过将几个条目添加SocksPort到程序的主配置文件中来完成,可以在上找到/etc/tor使用某些文本编辑器

打开文件/etc/tor/torrc,并将以下条目添加到文件末尾:

#  4 SOCKS-,       Tor-.

SocksPort 9050
SocksPort 9052
SocksPort 9053
SocksPort 9054

这里值得注意以下几点:

  • SocksPort . — , , SOCKS, .
  • SocksPort , , , - .
  • 9050 — , Tor- .
  • 9051. Tor , , , Tor.
  • 9051, , 1.

为了应用对配置文件所做的更改,请重新启动Tor客户端:

sudo /etc/init.d/tor restart

创建一个新的Node.js项目


为项目创建一个新目录。叫她superWebScraping

mkdir superWebScraping

让我们转到此目录并初始化一个空的Node项目:

cd superWebScraping && npm init -y

设置必要的依赖关系:

npm i --save puppeteer cheerio

使用Puppeteer处理网站


Puppeteer是一种不带用户界面的浏览器该浏览器使用DevTools协议ChromeChromium进行交互我们之所以不使用该库来处理诸如tor-request之的请求,是因为这样的库将无法处理作为单页Web应用程序创建的网站,其内容会动态加载。

创建一个文件index.js,并将以下代码放入其中。注释中描述了此代码的主要功能。

/**
 *   puppeteer.
 */
const puppeteer = require('puppeteer');

/**
 *   main  , 
 *     -.
 * ,      ,
 *   ,     
 *  puppeteer.
 */
async function main() {
  /**
   *  Chromium.   `headless`   false,
   *     .
   */
  const browser = await puppeteer.launch({
    headless: false
  });

  /**
   *   .
   */
  const page = await browser.newPage();

  /**
   *   ,   https://api.ipify.org.
   */
  await page.goto('https://api.ipify.org');

  /**
   *  3     .
   */
  setTimeout(() => {
    browser.close();
  }, 3000);
}

/**
 *  ,  main().
 */
main();

使用以下命令运行脚本:

node index.js

之后,Chromium浏览器窗口应出现在屏幕上,其中该地址已打开https://api.ipify.org


浏览器窗口,不使用Tor连接,

https://api.ipify.org之所以在浏览器窗口中打开它正是因为此页面可以显示从中访问它的公共IP地址。如果我在不使用Tor的情况下访问这些网站,则这些地址对我可见。

通过将以下键添加到带有传递的参数的对象中来更改上述代码puppeteer.launch

  /**
   *  Chromium.   `headless`  false,
   *     .
   */
  const browser = await puppeteer.launch({
  headless: false,
  
  //   .
  args: ['--proxy-server=socks5://127.0.0.1:9050']
});

我们向浏览器传递了一个参数--proxy-server此参数的值告诉浏览器,它应该使用在我们的计算机上运行并且可以在端口上访问的socks5代理服务器9050端口号是我们先前输入文件的端口号之一torrc

再次运行脚本:

node index.js

这次,在打开的页面上,您可以看到另一个IP地址。这是用于通过Tor网络查看站点的地址。


浏览器窗口,使用Tor连接,

在我的情况下,该窗口中出现一个地址144.217.7.33您可能还有其他地址。请注意,如果再次运行该脚本并使用相同的端口号(9050),则您将收到以前获得的相同IP地址。


重新启动浏览器窗口,使用Tor连接,

这就是为什么在Tor设置中我们打开了几个端口的原因。尝试将浏览器连接到其他端口。这将更改IP地址。

用Cheerio收集数据


现在我们有了一种方便的页面加载机制,现在该进行网页抓取了。为此,我们将使用cheerio这是一个HTML解析器,其API的构建方式与jQuery API相同我们的目标是从“黑客新闻”页面获取5个最新帖子。

转到Hacker News网站


黑客新闻网站

我们希望从打开的页面中获得5个新的头条新闻(现在是HAKMEM(1972),拉里·罗伯茨去世,等等)。使用浏览器开发人员工具检查了文章的标题,我注意到每个标题都放在<a>带有class的HTML元素中storylink


检查文档的结构

为了从页面的HTML代码中提取我们需要的内容,我们需要执行以下操作序列:

  • 在没有用户界面连接到Tor代理的情况下启动新的浏览器实例。
  • 创建一个新页面。
  • 转到地址https://news.ycombinator.com/
  • 获取页面的HTML内容。
  • 将页面的HTML内容加载到中cheerio
  • 创建一个数组来保存文章标题。
  • 用类访问元素storylink
  • 使用cheerio slice()方法获取前5个元素
  • 使用cheerio each()方法遍历结果元素
  • 将找到的每个标头写入数组。

以下是实现这些操作的代码:

const puppeteer = require('puppeteer');

/**
 *   cheerio.
 */
const cheerio = require('cheerio');

async function main() {
  const browser = await puppeteer.launch({
    /**
     *       (   ).
     */
    headless: true,
    args: ['--proxy-server=socks5://127.0.0.1:9050']
  });

  const page = await browser.newPage();

  await page.goto('https://news.ycombinator.com/');

  /**
   *      HTML-.
   */
  const content = await page.content();

  /**
   *    cheerio.
   */
  const $ = cheerio.load(content);


  /**
   *      .
   */
  const titles = [];

  /**
   *   ,   `storylink`.
   *  slice()      5   .
   *      each().
   */
  $('.storylink').slice(0, 5).each((idx, elem) => {
    /**
     *   HTML-,   .
     */
    const title = $(elem).text();
  
    /**
     *    .
     */
    titles.push(title);
  })

  browser.close();
  
  /**
   *     .
   */
  console.log(titles);
}

main();

运行此脚本后,将发生以下情况。


从页面代码中成功提取了前5个黑客新闻头条

使用不同的IP地址连续抓取


现在让我们讨论一下如何使用文件中指定的各种SOCKS端口torrc这很简单。我们将声明一个数组,每个数组都将包含一个端口号。然后将该函数重命名main()为一个函数,scrape()并声明一个新函数main(),该函数将调用该函数scrape(),并在每次调用时将其传递给新的端口号。

这是完成的代码:

const puppeteer = require('puppeteer');
const cheerio = require('cheerio');

async function scrape(port) {
  const browser = await puppeteer.launch({
    args: ['--proxy-server=socks5://127.0.0.1:' + port]
  });

  const page = await browser.newPage();
  await page.goto('https://news.ycombinator.com/');
  const content = await page.content();

  const $ = cheerio.load(content);

  const titles = [];

  $('.storylink').slice(0, 5).each((idx, elem) => {
    const title = $(elem).text();
    titles.push(title);
  });

  browser.close();
  return titles;
}

async function main() {
  /**
   *  SOCKS- Tor,    torrc. 
   */
  const ports = [
    '9050',
    '9052',
    '9053',
    '9054'
  ];
  
  /**
   *  -...
   */
  while (true) {
    for (const port of ports) {
      /**
       * ...  -    .
       */
      console.log(await scrape(port));
    }
  }
}

main();

摘要


现在,您可以使用工具进行匿名Web抓取。

亲爱的读者们!您曾经做过网页抓取吗?如果是这样,请告诉我们您使用哪些工具。

Source: https://habr.com/ru/post/undefined/


All Articles