暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何写一个淘宝商品详情页图片的爬虫

背井 2021-03-03
1762

本文将介绍写爬虫的思路以及提供一个具体的实现。需要依赖的工具有chrome浏览器和Node.js v12。



以商品 https://item.taobao.com/item.htm?id=555217237330 为例,我们需要爬取的是宝贝详情
tab下的所有图片。

爬虫的原理

爬虫是通过模拟用户访问给定的网站,执行某些操作或提取网站内容的程序。

爬取的思路

  1. 检查需要被爬取的内容所在dom节点的特征

  2. 根据特征搜索网页源码并定位相关内容

  3. 如果定位不到,在浏览器控制台进行全局搜索并通过Network Tab来过滤

思路实践

使用chrome浏览器打开 https://item.taobao.com/item.htm?id=555217237330。

我们右键一个待爬取的图片,检查元素,可以在chrome中看到如下显示:

先复制图片的链接,打开网页源码,在源码中进行搜索:

发现源码中并没有该图片地址,说明图片是通过脚本异步加载进来而不是和html页面一起返回的。

我们再通过检查元素,发现图片的父节点有个id J_DivItemDesc
, 有经验的开发者会想到,脚本是通过这个id来定位图片容器的。所以我们在源码中搜索这个id试试:

我们发现,该id出现了2次,定位到它们:

  1. 这个是dom节点本身: 

  2. 这个是js脚本:

注意,从js脚本中,我们不仅发现了id, 还发现descUrl
这个属性,我们猜测它指向的就是详情图片。

访问试试:

可以发现,该url返回了一连窜的图片。对比可知,它们确实是商品的详情图片。

通过以上步骤,我们解决了如何查询图片来源的问题。如果我们眼瞎:),没注意到descUrl
这个属性。有其它办法定位到图片的来源吗?

..
..
..
..

我们再提供另一种方案。

首先,在浏览器控制台进行全局搜索(cmd+option+f),搜索的是之前复制的详情图片地址:

我们不仅搜到了图片,还看到了请求源: desc.alicdn... 。接着我们看看这个请求是在哪里发出的:

从item.htm中发出,即请求的信息写在item.htm源码中,所以我们只需要在源码中搜索desc.alicdn
便能找到图片在哪里了:

殊途同归,我们又定位到了descUrl

以上是2种定位所需要内容的方式。接下来给一个具体的代码实现。

代码实现

我们使用TypeScript来写,以增加可读性。

taobao.ts

    import request from 'request';


    /**
    * 获取淘宝商品详情页面的html源码
    * @param {string} itemUrl 页面地址,比如 https://item.taobao.com/item.htm?id=555217237330
    * @return {Promise<string>} 页面html源码
    */
    function fetchHTML(itemUrl: string): Promise<string> {
    return new Promise((resolve, reject) => {
    request({url: itemUrl}, (err, res, body) => {
    err ? reject(err) : resolve(body)
    });
    })
    }


    /**
    * 获取淘宝商品详情图片的源码
    * @param {string} descUrl 图片地址
    * 比如 desc.alicdn.com/i4/550/210/555217237330/TB1QacrQgHqK1RjSZFP8qwwapla.desc%7Cvar%5Edesc%3Bsign%5E68d509b027183b2087ae0ee50be0e288%3Blang%5Egbk%3Bt%5E1554975361
    * @return {Promise<string>} 图片源码
    */
    function fetchImages(descUrl: string): Promise<string> {
    return new Promise((resolve, reject) => {
    request({url: descUrl}, (err, res, body) => {
    err ? reject(err) : resolve(body)
    });
    });
    }




    // 用来解析图片源码地址
    const desc_url_regex = /(desc.alicdn.com[^']+?)'/;
    // 用来解析图片
    const image_regex = /src="([^"]+?)"/;


    /**
    * 获取淘宝详情图片列表
    *
    * 返回的是一个图片地址迭代器,方便按需解析(不是所有时候都需要所有图片)
    *
    * @param {string} itemUrl 商品url
    * @return {AsyncIterableIterator<String>} 图片地址迭代器
    */
    export async function* getImages(itemUrl: string): AsyncIterableIterator<String> {
    const html = await fetchHTML(itemUrl);
    const [, descUrl] = desc_url_regex.exec(html);


    const imageHtml = await fetchImages('http://' + descUrl);


    for (const matches of imageHtml.matchAll(image_regex)) {
    yield matches[1]
    }
    }



    taobao.test.js

      /**
      * 获取淘宝商品详情图片的源码
      * @param {string} descUrl 图片地址
      * 比如 desc.alicdn.com/i4/550/210/555217237330/TB1QacrQ...
      * @return {Promise<string>} 图片源码
      */
      function fetchImages(descUrl: string): Promise<string> {
      return new Promise((resolve, reject) => {
      request({url: descUrl}, (err, res, body) => {
      err ? reject(err) : resolve(body)
      });
      });
      }


      结束语

      以上只是利用桌面端浏览器定位爬虫内容的方式。移动的app,因为没有html页面,则需要另一种方式,比如截取app请求并作出分析。以后有空再写。

      写爬虫只是第一步,部署运行的过程中会有另外的问题。比如部分网站会做反爬处理(限制ip,限制访问次数等)。如何减少反爬带来的影响?

      欢迎评论或私聊。


      文章转载自背井,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论