返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
爬虫

Selenium爬虫实战:截取网页上的图片

前言 同样是为了刷课,没想到工作后依然和大学一样逃脱不了需要刷网课的命运…… 正文 直接说干货了,截取图片,需要截取的图片是什么图片大家都懂(说的就是你,验证码),其他图片的话不需要截取,直接拿到地址下载就行,验证码不行,同样的地址再访问一次内容就变了。 我不知道为啥selenium不能直接把特定img元素的图片拿出来,太反人类了。 根据我找到的资料,主要有两种思路,一种是模拟鼠标操作,在验证码上

曦远 (DealiAxy)约 10 分钟
目录5 个章节

前言

同样是为了刷课,没想到工作后依然和大学一样逃脱不了需要刷网课的命运……

正文

直接说干货了,截取图片,需要截取的图片是什么图片大家都懂(说的就是你,验证码),其他图片的话不需要截取,直接拿到地址下载就行,验证码不行,同样的地址再访问一次内容就变了。

我不知道为啥selenium不能直接把特定img元素的图片拿出来,太反人类了。

根据我找到的资料,主要有两种思路,一种是模拟鼠标操作,在验证码上面点击右键,然后选择另存为,把验证码保存到本地之后再来读取…… 我不理解为啥有这种这么思路清奇的操作,右键另存为的一个很大问题就是你根本没法控制图片存在那里,这也导致这个爬虫程序不具备通用性!所以直接pass掉。

另一种是先对整个网页截图,然后再按照验证码img元素的位置和大小,定位并且裁剪出小的验证码图片来,理想情况下是可以的,但是经过我多次测试发现不同浏览器裁剪出来图片有不同偏移和缩放,不知道是哪里出了问题,只能硬编码微调,吐了。尽管方法不完美,但是也勉强够用吧,分享一下代码……

代码

这次是用C#(WinForm)做的,虽然只是代码片段,不过截图+裁剪保存部分还是可以参考一下的。

后面的验证码识别是顺带加上的,用了百度的接口,准确率堪忧。

setStatusMsg1("正在提取验证码");
var verifyCode = currentBrowser.WebDriver.FindElement(By.XPath("/html/body/spk-root/spk-login-page/div/section/div[3]/div[2]/div[2]/form/div[3]/div[2]/img"));
setStatusMsg2("浏览器截屏");
// 设置浏览器大小
currentBrowser.WebDriver.Manage().Window.Size = new Size(1280, 800);
// 浏览器截屏
var screenshot = ((ITakesScreenshot)currentBrowser.WebDriver).GetScreenshot();
var screenImagePath = Path.Combine(Path.GetTempPath(), $"{System.Guid.NewGuid().ToString("N")}.jpg");
// 保存截屏图片
setStatusMsg2("保存截屏");
screenshot.SaveAsFile(screenImagePath, ScreenshotImageFormat.Jpeg);

// 裁剪验证码
setStatusMsg2("裁剪验证码");
var codeImagePath = screenImagePath.Replace(".jpg", "_code.jpg");

int x, y, width, height;

// 使用js来获取图片的位置等信息
switch (currentBrowser.BrowserType) {
    case BrowserEnum.Chrome:
        x = Convert.ToInt32((long)((IJavaScriptExecutor)currentBrowser.WebDriver).ExecuteScript("return document.querySelector('body > spk-root > spk-login-page > div > section > div.login-body.clearfix > div.login-right > div.form-con > form > div.qr-code > div.qrcode-box.clearfix > img').x"));
        y = Convert.ToInt32((long)((IJavaScriptExecutor)currentBrowser.WebDriver).ExecuteScript("return document.querySelector('body > spk-root > spk-login-page > div > section > div.login-body.clearfix > div.login-right > div.form-con > form > div.qr-code > div.qrcode-box.clearfix > img').y"));
        width = verifyCode.Size.Width;
        height = verifyCode.Size.Height;
        // 验证码位置调整
        //x += 20;
        //y += 8;
        // 验证码大小调整
        width += 30;
        height += 15;
        break;
    default:
        x = verifyCode.Location.X;
        y = verifyCode.Location.Y;
        width = verifyCode.Size.Width;
        height = verifyCode.Size.Height;
        break;
}

var codeBitmap = new Bitmap(width, height);
var codeGraphics = Graphics.FromImage(codeBitmap);

var destRec = new Rectangle(0, 0, width, height);
var srcRec = new Rectangle(x, y, width, height);
setStatusMsg2(srcRec.ToString());
codeGraphics.DrawImage(new Bitmap(screenImagePath), destRec, srcRec, GraphicsUnit.Pixel);
// 保存验证码图片
codeBitmap.Save(codeImagePath, ImageFormat.Jpeg);

// 显示图片
picVerifyCode.Load(codeImagePath);
picVerifyCode.Tag = codeImagePath;

// 验证码识别
var result = BaiduAiSdk.VerifyCode(codeImagePath);
if (result.Length > 0) {
    txtVerifyCode.Text = result;
    FrmTips.ShowTipsSuccess(this, $"验证码识别成功,识别结果:{result}");

    var input = currentBrowser.WebDriver.FindElement(By.XPath("/html/body/spk-root/spk-login-page/div/section/div[3]/div[2]/div[2]/form/div[3]/div[2]/input"));
    input.Clear();
    input.SendKeys(result);
} else
    FrmTips.ShowTipsError(this, "验证码识别失败,请重试!");

参考资料

欢迎交流

程序设计实验室专注于互联网热门新技术探索与团队敏捷开发实践,在公众号「程序设计实验室」后台回复 linux、flutter、c#、netcore、android、kotlin、java、python 等可获取相关技术文章和资料,同时有任何问题都可以在公众号后台留言~

_EOF_

Selenium爬虫实战:截取网页上的图片

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

一个玄学的爬虫bug竟让我放弃Python语言!?背后的原因令人唏嘘~

每一位成功的程序员,背后也许都站着无数秃头的男人——为其提供各种开发工具&代码库,当然也包括…… 各种玄学bug…… 玄学的开端 最近在用Python做一个爬虫项目的时候遇到一个很奇怪的问题,而且还不是每次都会触发,实在是令人费解…… 报错信息如下: UnicodeEncodeError: 'latin-1' codec can't encode character '\u2026' in pos

2021-12-18 · 爬虫 · 约 1 分钟

Selenium爬虫实践:ajax请求抓包、浏览器退出

前言 最近在搞公司内部系统,累的一批,需要从另一个内部系统导出数据存到数据库做分析,有大量的数据采集工作,又没办法去直接拿到那个系统的接口,太难了,只能爬虫,但是cookie还经常失效,为了不每次登录失效就来找我重新注入Cookie,我写了一个手机版的网页,用来控制后台的selenium自动登录,截取token和cookie。 ajax请求抓包方案 搜索资料的过程真的痛苦,不过还好这时间没有白花,

2022-05-27 · 爬虫 · 约 1 分钟

爬虫笔记:代理池和线程池

前言 爬虫和反爬虫是一对矛和盾,反爬虫很常见的一个方法就是封IP,一个IP短时间内频繁访问,可以做限流或者是加入黑名单,我之前的后台开发相关博客也有涉及这一块。 不过今天说的是爬虫,所以应对的方法就是用代理池,每次请求都用不同的IP就行,再加上UA模拟,完全是正常用户的行为,可以避开限流和黑名单反爬。 然后爬虫是一种IO密集型程序,如果全程单线程执行那会很慢,因此可以用多线程来提高数据采集效率,不

2022-02-12 · 爬虫 · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…