0

I'm using selenium-webdriver with nodejs to scrap a page. One element of the page is a captcha that i want to grab the image. I've been searching but i only found java or python codes to do that.

So far i got:

function writeScreenshot(data, name) {
  name = name || 'ss.png';
  var screenshotPath = '/Users/Projects/screenshots/';
  fs.writeFileSync(screenshotPath + name, data, 'base64');
};

driver.takeScreenshot().then(function(data) {
  writeScreenshot(data, 'out1.png');
});

//location of captcha
var capt = driver.findElement(webdriver.By.xpath('myXPath');
var location = capt.getLocation();
var captAltura = capt.getSize().getHeight();
var captLargura = capt.getSize().getWidth();

The screenshot of the page is working. The second part where "//location of captcha" is set i'm not sure because i do not know how to proceed. How can i crop the image?

-- Update (Html code):

<form name="form" method="POST">
<table width="750" cellspacing="0" cellpadding="0" border="0">
  <tbody>
    <tr bgcolor="#CCCCCC">
      <td width="100%" height="31" align="center">
        <font class="code">Code:</font>
        <input type="text" name="captcha" size="4" maxlength="4" value="" title="Security Code" class="inputcaptcha" onclick="this.select()">
        <img src="captcha.php" width="90" align="middle">
      </td>
    </tr>
  </tbody>
</table>
</form>
ziad.ali
  • 321
  • 4
  • 20
  • Probably need to change `'myXPath'` to the xpath of the captcha. – Ouroborus Dec 04 '16 at 11:43
  • @Ouroborus Well, i just edited for the question. In the code the xpath is correct. Once i got all those information, how can i crop the entire webpage screenshot to just the captcha? – ziad.ali Dec 04 '16 at 11:48
  • You can't. You have two different things going on. The first part of your code is getting a screenshot of the page. This isn't particularly useful in relation to the captcha. The last part is trying to actually locate the captcha image within the page. For that, locate the element of the captcha image, extract the url for the image, retrieve the image separately. – Ouroborus Dec 04 '16 at 11:55
  • @Ouroborus The thing is, the captcha is a dynamic image. Like this: . So, i was trying to do this: http://stackoverflow.com/a/13834607/3383534 but i don't know how to implement into my code. – ziad.ali Dec 04 '16 at 13:01
  • You need to create just screenshot of the element with captcha. Not whole page. It doesn't matter that it's dynamic image, it has to be in some static div or something on that page. – pagep Dec 04 '16 at 13:32
  • @pagep I added the html code where this image is located. Outside of that, there's only a div that cover the entire form. Is it possible to take a screenshot by having the xpath of the element? – ziad.ali Dec 04 '16 at 13:43

2 Answers2

1

screenshotElement: function (driver, locator) {
    return new Promise(async (resolve, reject) => {
      try {
        let base64Image = await driver.takeScreenshot();
        let decodedImage = new Buffer(base64Image, "base64");
        let dimensions = await driver.findElement(By.xpath(locator)).getRect();
        let xLoc = xext + dimensions.x;
        let yLoc = yext + dimensions.y;
        let eWidth = eleWidth + (xLoc * 2 - 300);
        let eHeight = eleHeight + yLoc;
        let image = await Jimp.read(decodedImage);
        image.crop(xLoc, yLoc, eWidth, eHeight).getBase64(Jimp.AUTO, (err, data) => {
          if (err) {
            console.error(err)
            reject(err)
          }
          imgConvert.fromBuffer({
            buffer: data,
            output_format: "jpg"
          }, function (err, buffer, file) {
            if (!err) {
              let croppedImageDataBase64 = buffer.toString('base64')
              resolve(croppedImageDataBase64)
            }
            else {
              console.error(err.message);
              reject(err)
            }
          })
        });
      } catch (err) {
        console.error(err.message);
        reject(err)
      }
    })
  },

Here's my solution, I grappled with it for a long time as well.

Nico Mee
  • 869
  • 5
  • 6
0

I ended up using the library easyimage. Reference: https://stackoverflow.com/a/32111192/3383534

First you take a screenshot of the hole page and then crop to the element you want.

Here's how i did it:

function cropInFile (valorWidth, valorHeight, valorX, valorY, srcFile){
    easyimg.crop(
        {
            src: pathFile,
            dst: pathFile,
            cropwidth: valorWidth,
            cropheight: valorHeight,
            x: valorX,
            y: valorY,
            gravity: 'North-West'
        },
        function(err, stdout, stderr) {
            if (err) throw err;
        }
    );
};

These parameters: valorWidth, valorHeight, valorX, valorY are for the element you want. And the last is the first screenshot taken.

Community
  • 1
  • 1
ziad.ali
  • 321
  • 4
  • 20