zoukankan      html  css  js  c++  java
  • 数据采集实战(二)-- 京粉商品

    1. 概述

    京粉(https://union.jd.com/)是京东联盟下的网站,通过分享其中的商品链接可以赚取佣金,类似淘客联盟。

    采集京粉的商品,既可以练习 puppeteer的使用,平时想在京东购物时,也能用得上(采集看看有类似商品的价格和评价)。

    2. 主要流程

    采集的流程很简单:
    image.png

    2.1 登录

    登录本来是很简单的步骤,只是京粉的登录有点特殊,它的登录框是在 iframe 中,所以,加载完网页后可能登录框并没有出现。
    需要加载完 iframe 之后才能录入用户名/密码。
    image.png

    登录模块的代码如下:

    const username = "YOUR NAME";
    const passwd = "YOUR PASSWORD";
    
    // 登录
    const login = async (page) => {
      await page.goto("https://union.jd.com/index");
    
      // 等待加载 login 的 iframe
      await page.waitForSelector("#indexIframe");
      const frame = (await page.frames())[1];
    
      await frame.waitForSelector("#loginname");
      // 输入用户名和密码 登录
      await frame.type("#loginname", username, { delay: 100 });
      await frame.type("#nloginpwd", passwd, { delay: 100 });
      await frame.click("#paipaiLoginSubmit");
    };
    
    export default login;
    

    2.2 进入“商品检索”菜单

    登录成功后,进入首页,点击左侧的菜单进入“商品检索”页面。
    image.png

    注意这里直接使用 page 的 click 方法是无效的,需要使用如下方式:

    // 进入商品界面
    const productPage = async (page) => {
      await page.waitForSelector(".menu-wrapper");
    
      // 直接选择无法点击,只能用 page.evaluate 方法来点击
      // 【我要推广】 菜单
      await page.evaluate(
        (selector) => document.querySelectorAll(selector)[0].click(),
        ".el-submenu__title>span"
      );
      
      // 【商品推广】 菜单
      await page.evaluate(
        (selector) => document.querySelectorAll(selector)[1].click(),
        "li.el-menu-item>span"
      );
    };
    

    2.3 录入检索条件并开始检索

    商品推广页面支持的检索条件很多,这里只输入佣金价格的范围来检索:

    // 检索商品(佣金比例范围,价格范围)
    const searchProduct = async (page, feeMin, feeMax, priceMin, priceMax) => {
      await page.waitForSelector(".imgbox");
    
      await page.waitForSelector("input.el-input__inner");
      const inputs = await page.$$("input.el-input__inner");
    
      // IMPORTANT 使用click才能输入完整,使用 focus,无法输入完整
      await inputs[1].click();
      // await inputs[1].focus();
      await inputs[1].type(feeMin, { delay: 200 });
      await inputs[2].click();
      await inputs[2].type(feeMax, { delay: 200 });
      await inputs[3].click();
      await inputs[3].type(priceMin, { delay: 200 });
      await inputs[4].click();
      await inputs[4].type(priceMax, { delay: 200 });
    
      // 佣金和价格输入之后,鼠标必须浮在输入框上,才会出现确定按钮去检索
      const divs = await page.$$(".commission");
      // div对应的确认按钮在隐藏的 div中
      let popover = await divs[1].evaluate((node) =>
        node.getAttribute("aria-describedby")
      );
    
      // 通过 hover()函数,让确定按钮显示出来
      await inputs[4].hover();
      await page.waitForSelector(`#${popover}`, { visible: true });
      await page.click(`#${popover}>.el-button--primary`);
    };
    
    export default searchProduct;
    

    佣金的范围(feeMinfeeMax),价格范围(priceMinpriceMax)是通过参数传入的。

    image.png

    2.4 保存网页

    保存网页很简单,**puppeteer **提供了获取整个HTML页面的接口。

    // 保存网页内容到指定路径
    const savePage = async (page, dirname, filename) => {
      const html = await page.content();
      await saveContent(dirname, filename, html);
    };
    
    // 保存解析后的网页内容到指定路径
    const saveContent = async (dirname, filename, content) => {
      if (!mkdirsSync(dirname)) {
        console.error("mkdir save page dir ERROR!");
        return;
      }
    
      fs.writeFileSync(path.join(dirname, filename), content);
    };
    

    2.5 进入下一页

    在页面的最下方有翻页的按钮,只要找到下一页的按钮即可。
    image.png
    点击下一页的函数如下:

    // 进入下一页
    const nextPage = async (page) => {
      await page.waitForSelector(".el-pagination");
      const pageBottons = await page.$$(".el-pagination>button");
      // pageBottons[0] -> 上一页   pageBottons[1] -> 下一页
      await pageBottons[1].click();
      await page.waitForNavigation();
    };
    
    export default nextPage;
    

    3. 运行效果

    jinfen.gif

    4. 总结

    以上通过 puppeteer 采集京粉商品数据的实战中,技术要点主要有:

    1. 加载 iframe 并自动登录
    2. 点击menu 菜单迁移到商品页面
    3. 在文本框中输入检索条件
    4. 自动翻页

    5. 注意事项

    爬取数据只是为了研究学习使用,本文中的代码遵守:

    1. 如果网站有 robots.txt,遵循其中的约定
    2. 爬取速度模拟正常访问的速率,不增加服务器的负担
    3. 只获取完全公开的数据,有可能涉及隐私的数据绝对不碰
  • 相关阅读:
    拓扑排序,bitset~[JSOI2015]最小表示
    字符串算法~KMP
    校内团队训练赛2
    校内团队训练赛
    CodeForces
    莫队算法基础与练习
    lintcode-452-删除链表中的元素
    lintcode-451-两两交换链表中的节点
    lintcode-450-K组翻转链表
    lintcode-445-余弦相似度
  • 原文地址:https://www.cnblogs.com/wang_yb/p/15063997.html
Copyright © 2011-2022 走看看