在selenium开的浏览器中,响应头修改插件失效,如何解决

2020-12-28 15:14发布

用selenium打开加载了自己写的chrome扩展的一个浏览器,其中响应头修改失效了,在正常开发启动的浏览器中没有发现这个问题,请问哪位大佬遇到过这种情况,该如何解决,修改响应头回调代码如下:fun...

用selenium打开加载了自己写的chrome扩展的一个浏览器,其中响应头修改失效了,在正常开发启动的浏览器中没有发现这个问题,请问哪位大佬遇到过这种情况,该如何解决,修改响应头回调代码如下:

function callback(requestDetails) {
requestDetails.responseHeaders.forEach(header => {
if (header.name == 'Content-Type' && header.value == "text/plain") {
header.value = header.value + ";charset=UTF-8";
}});
return {responseHeaders: requestDetails.responseHeaders};
}


2条回答

先看浏览器开发工具下,请求包是否修改了头
直接使用抓包工具,如wireshark,抓下这个端口的网络包,这是最终的网络传输包,如果修改了肯定就是修改了,而且可以看到传递的真实数据流

ann
3楼 · 2020-12-30 08:52





前言

本文利用selenium、百度OCR在线文字识别完成某一网站的模拟登陆操作,通过OCR识别验证码完成登陆后返回cookie,常用于Java爬虫。

准备工作

百度智能云官网创建OCR图像识别项目,获取项目的APIKey以及SecretKey下载百度OCR需要用到的工具类下载chromedriver.exe驱动

OCR项目创建

注册登录百度智能云账号,网址:https://login.bce.baidu.com/选择文字识别功能并且完成应用创建应用创建完毕后点击管理应用,获取项目的APIKey以及SecretKey这里选用网络图片文字识别,和通用文字识别相比识别率会更高,对应api学习网址https://cloud.baidu.com/doc/OCR/s/Sk3h7xyad

对应Util工具类的下载(5个)

*https://ai.baidu.com/file/658A35ABAB2D404FBF903F64D47C1F72

*https://ai.baidu.com/file/C8D81F3301E24D2892968F09AE1AD6E2

*https://ai.baidu.com/file/544D677F5D4E4F17B4122FBD60DB82B3

*https://ai.baidu.com/file/470B3ACCA3FE43788B5A963BF0B625F3

*第五个手动添加,如下


importorg.json.JSONObject;

importjava.io.BufferedReader;

importjava.io.InputStreamReader;

importjava.net.HttpURLConnection;

importjava.net.URL;

importjava.util.List;

importjava.util.Map;


/**

*获取token类

*/

publicclassAuthService{


/**

*获取权限token

*@return返回示例:

*{

*"access_token":"24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",

*"expires_in":2592000

*}

*/

publicstaticStringgetAuth(){

//官网获取的APIKey更新为你注册的

StringclientId="百度云应用的AK";

//官网获取的SecretKey更新为你注册的

StringclientSecret="百度云应用的SK";

returngetAuth(clientId,clientSecret);

}


/**

*获取API访问token

*该token有一定的有效期,需要自行管理,当失效时需重新获取.

*@paramak-百度云官网获取的APIKey

*@paramsk-百度云官网获取的SecuretKey

*@returnassess_token示例:

*"24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"

*/

publicstaticStringgetAuth(Stringak,Stringsk){

//获取token地址

StringauthHost="https://aip.baidubce.com/oauth/2.0/token?";

StringgetAccessTokenUrl=authHost

//1.grant_type为固定参数

+"grant_type=client_credentials"

//2.官网获取的APIKey

+"&client_id="+ak

//3.官网获取的SecretKey

+"&client_secret="+sk;

try{

URLrealUrl=newURL(getAccessTokenUrl);

//打开和URL之间的连接

HttpURLConnectionconnection=(HttpURLConnection)realUrl.openConnection();

connection.setRequestMethod("GET");

connection.connect();

//获取所有响应头字段

Map>map=connection.getHeaderFields();

//遍历所有的响应头字段

for(Stringkey:map.keySet()){

System.err.println(key+"--->"+map.get(key));

}

//定义BufferedReader输入流来读取URL的响应

BufferedReaderin=newBufferedReader(newInputStreamReader(connection.getInputStream()));

Stringresult="";

Stringline;

while((line=in.readLine())!=null){

result+=line;

}

/**

*返回结果示例

*/

System.err.println("result:"+result);

JSONObjectjsonObject=newJSONObject(result);

Stringaccess_token=jsonObject.getString("access_token");

returnaccess_token;

}catch(Exceptione){

System.err.printf("获取token失败!");

e.printStackTrace(System.err);

}

returnnull;

}


}


下载Chromedriver.exe插件

首先查看自己谷歌浏览器的版本,地址栏输入chrome://version/浏览器版本号与驱动版本对应关系下载地址https://npm.taobao.org/mirrors/chromedriver/其他版本对应关系

chromedriver版本支持的chrome版本v2.46v72-74v2.45v70-72v2.44v69-71v2.43v69-71v2.42v68-70v2.41v67-69v2.40v66-68v2.39v66-68v2.38v65-67v2.37v64-66v2.36v63-65v2.35v62-64v2.34v61-63v2.33v60-62v2.32v59-61v2.31v58-60v2.30v58-60v2.29v56-58v2.28v55-57v2.27v54-56v2.26v53-55v2.25v53-55v2.24v52-54v2.23v51-63v2.22v49-52v2.21v46-50v2.20v43-48v2.19v43-47v2.18v43-42v2.17v42-43v2.16v42-45v2.15v40-43v2.14v39-42v2.13v38-41v2.12v36-40v2.11v36-40v2.10v33-36v2.9v31-34

ps:下载完毕后把chromedriver.exe放置在运行工程的根目录下

代码编写

依赖导入


org.seleniumhq.selenium

selenium-java

3.141.59


org.slf4j

slf4j-log4j12

1.7.25



com.baidu.aip

java-sdk

4.4.1



百度OCR验证码识别类

/**

*@Author:zf

*@Date:2020/08/2609:08:35

*@Desc:调用百度OCR接口来识别验证码,直接返回识别后得到的字符串内容

*/

publicclassBaiDuOcr{


//传入参数为图片的本地地址

publicstaticStringwebImage(StringimageUrl){


//请求url

Stringurl="https://aip.baidubce.com/rest/2.0/ocr/v1/webimage";

//识别得到的字串

Stringresult=null;


try{

//本地文件路径

StringfilePath=imageUrl;

byte[]imgData=FileUtil.readFileByBytes(filePath);

StringimgStr=Base64Util.encode(imgData);

StringimgParam=URLEncoder.encode(imgStr,"UTF-8");


Stringparam="image="+imgParam;


//获取百度Ocrtoken

StringaccessToken=AuthService.getAuth(APIKey,SecretKey);


result=HttpUtil.post(url,accessToken,param);

result=result.substring(result.lastIndexOf(":")+3,result.lastIndexOf("\""));


}catch(Exceptione){

e.printStackTrace();

}


returnresult;

}

}


模拟登陆类

importorg.apache.commons.io.FileUtils;

importorg.openqa.selenium.*;

importorg.openqa.selenium.chrome.ChromeDriver;

importorg.openqa.selenium.chrome.ChromeOptions;


importjavax.imageio.ImageIO;

importjava.awt.image.BufferedImage;

importjava.io.File;

importjava.io.IOException;

importjava.util.regex.Matcher;

importjava.util.regex.Pattern;


/**

*@Author:zf

*@Date:2020/08/2611:38:06

*@Desc:采用selenium+百度OCR,通过截取网页上的验证码图片发送至百度OCR处理后完成登录操作,并且返回对应的cookie

*/

publicclassCookieLogin{


privatestaticStringcookies=null;


/*

*参数说明:

*url:请求地址url

*nameId:用户名输入框所在标签的id

*pwdId:密码输入框所在标签的id

*imageId:验证码图片所在标签的id

*codeId:验证码输入框所在标签的id

*loginClass:登录按钮所在标签的class

*name:用户名

*pwd:密码

**/

publicstaticStringdoLogin(Stringurl,StringnameId,StringpwdId,StringimageId,StringcodeId,

StringloginClass,Stringname,Stringpwd){

System.getProperties().setProperty("webDriver.chrome.dirver","chromedriver.exe");


//启动模拟浏览器

ChromeOptionschromeOptions=newChromeOptions();

chromeOptions.setHeadless(true);


WebDriverdriver=newChromeDriver(chromeOptions);

driver.get(url);

driver.manage().window().maximize();


//定义验证码变量

Stringverify=null;


//寻找账号编辑框

driver.findElement(By.id(nameId)).clear();

driver.findElement(By.id(nameId)).sendKeys(name);


//寻找密码编辑框

driver.findElement(By.id(pwdId)).clear();

driver.findElement(By.id(pwdId)).sendKeys(pwd);


//创建一个时间戳,防止验证码图片文件重名

Stringtimestamp=System.currentTimeMillis()+"";


//寻找验证码容器

WebElementele=driver.findElement(By.id(imageId));


//创建一个快照

Filescreenshot=((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);


//读取截图

BufferedImagefullImg=null;

try{

fullImg=ImageIO.read(screenshot);


//获取页面上元素的位置

org.openqa.selenium.Pointpoint=ele.getLocation();


//获取元素宽高

inteleWidth=ele.getSize().getWidth();

inteleHeight=ele.getSize().getHeight();

//计算比例

floatrate=(float)fullImg.getWidth()/1280;


//裁剪整个页面截图只得到元素截图

BufferedImageeleScreenshot=fullImg.getSubimage((int)(point.getX()*rate),

(int)(point.getY()*rate),

(int)(eleWidth*rate),

(int)(eleHeight*rate));

ImageIO.write(eleScreenshot,"png",screenshot);


//将验证码截图保存到本地

FilescreenshotLocation=newFile(timestamp+".jpg");

FileUtils.copyFile(screenshot,screenshotLocation);


//调用百度OCR

StringfilePath=timestamp+".jpg";

Stringresult=BaiDuOcr.webImage(filePath);


//删除本地文件

screenshotLocation.delete();


//寻找验证码编辑框

driver.findElement(By.id(codeId)).clear();

driver.findElement(By.id(codeId)).sendKeys(result);


//模拟点击登录按钮

driver.findElement(By.className(loginClass)).click();


Thread.sleep(5000);


//获取cookie信息

cookies=driver.manage().getCookies().toString();

}catch(IOExceptione){

e.printStackTrace();

}catch(InterruptedExceptione){

e.printStackTrace();

}finally{

driver.quit();

}


returncookies;

}


}


调用类

/**

*@Author:zf

*@Date:2020/08/2722:42:19

*/

publicclassgetCookie{


publicstaticvoidmain(String[]args){

StringCookie=CookieLogin.doLogin(请求地址url,

用户名输入框所在标签的id,

密码输入框所在标签的id,

验证码图片所在标签的id,

"验证码输入框所在标签的id,

登录按钮所在标签的class,

用户名,

密码);

System.out.println(Cookie);

}


}


配置文件

log4j.properties

log4j.rootLogger=INFO,stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d%p[%c]-%m%n

log4j.appender.logfile=org.apache.log4j.FileAppender

log4j.appender.logfile.File=target/spring.log

log4j.appender.logfile.layout=org.apache.log4j.PatternLayout

log4j.appender.logfile.layout.ConversionPattern=%d%p[%c]-%m%n


selenium.properties

#WhatWebDrivertouseforthetests

#driver=phantomjs

#driver=firefox

driver=chrome

#driver=http://localhost:8910

#driver=http://localhost:4444/wd/hub

#PhantomJSspecificconfig(changeaccordingtoyourinstallation)

#phantomjs_exec_path=/Users/Bingo/bin/phantomjs-qt5

#phantomjs_exec_path=d:/phantomjs.exe

#chrome_exec_path=E:\\demo\\crawler\\chromedriver.exe

#phantomjs_driver_path=/Users/Bingo/Documents/workspace/webmagic/webmagic-selenium/src/main.js

#phantomjs_driver_loglevel=DEBUG

chrome_driver_loglevel=DEBUG


总结

最近在学习Java的爬虫,在网络上查找使用selenium进行模拟识别验证码登录后返回cookie的教程非常的少,因此写下这篇教程。此外,在爬虫程序的实际开发中,对于爬虫带验证码登录的情况非常多见,对于验证码比较清晰的情况可以使用教程里的百度OCR或tesseract-ocr工具进行识别,但是对于比较复杂的验证码以及滑块、文字类的复杂验证码,一般会接入打码平台来完成。


相关问题推荐

  • 回答 3

    换行。比如,print hello\nworld效果就是helloworld\n就是一个换行符。\是转义的意思,'\n'是换行,'\t'是tab,'\\'是,\ 是在编写程序中句子太长百,人为换行后加上\但print出来是一整行。...

  • 回答 42

    十种常见排序算法一般分为以下几种:(1)非线性时间比较类排序:a. 交换类排序(快速排序、冒泡排序)b. 插入类排序(简单插入排序、希尔排序)c. 选择类排序(简单选择排序、堆排序)d. 归并排序(二路归并排序、多路归并排序)(2)线性时间非比较类排序:...

  • 回答 70
    已采纳

    前景很好,中国正在产业升级,工业机器人和人工智能方面都会是强烈的热点,而且正好是在3~5年以后的时间。难度,肯定高,要求你有创新的思维能力,高数中的微积分、数列等等必须得非常好,软件编程(基础的应用最广泛的语言:C/C++)必须得很好,微电子(数字电...

  • 回答 28

    迭代器与生成器的区别:(1)生成器:生成器本质上就是一个函数,它记住了上一次返回时在函数体中的位置。对生成器函数的第二次(或第n次)调用,跳转到函数上一次挂起的位置。而且记录了程序执行的上下文。生成器不仅记住了它的数据状态,生成器还记住了程序...

  • 回答 9

    python中title( )属于python中字符串函数,返回’标题化‘的字符串,就是单词的开头为大写,其余为小写

  • 回答 6

    第一种解释:代码中的cnt是count的简称,一种电脑计算机内部的数学函数的名字,在Excel办公软件中计算参数列表中的数字项的个数;在数据库( sq| server或者access )中可以用来统计符合条件的数据条数。函数COUNT在计数时,将把数值型的数字计算进去;但是...

  • 回答 1

    head是方法,所以需要取小括号,即dataset.head()显示的则是前5行。data[:, :-1]和data[:, -1]。另外,如果想通过位置取数据,请使用iloc,即dataset.iloc[:, :-1]和dataset.iloc[:, -1],前者表示的是取所有行,但不包括最后一列的数据,结果是个DataFrame。...

  • Python入门简单吗2021-09-23 13:21
    回答 45

    挺简单的,其实课程内容没有我们想象的那么难、像我之前同学,完全零基础,培训了半年,直接出来就工作了,人家还在北京大公司上班,一个月15k,实力老厉害了

  • 回答 4

    Python针对众多的类型,提供了众多的内建函数来处理(内建是相对于导入import来说的,后面学习到包package时,将会介绍),这些内建函数功用在于其往往可对多种类型对象进行类似的操作,即多种类型对象的共有的操作;如果某种操作只对特殊的某一类对象可行,Pyt...

  • 回答 8

     相当于 ... 这里不是注释

  • 回答 4

    还有FIXME

  • 回答 3

    python的两个库:xlrd和xlutils。 xlrd打开excel,但是打开的excel并不能直接写入数据,需要用xlutils主要是复制一份出来,实现后续的写入功能。

  • 回答 8

    单行注释:Python中的单行注释一般是以#开头的,#右边的文字都会被当做解释说明的内容,不会被当做执行的程序。为了保证代码的可读性,一般会在#后面加一两个空格然后在编写解释内容。示例:#  单行注释print(hello world)注释可以放在代码上面也可以放在代...

  • 回答 2

    主要是按行读取,然后就是写出判断逻辑来勘测行是否为注视行,空行,编码行其他的:import linecachefile=open('3_2.txt','r')linecount=len(file.readlines())linecache.getline('3_2.txt',linecount)这样做的过程中发现一个问题,...

  • 回答 4

    或许是里面有没被注释的代码

  • 回答 26

    自学的话要看个人情况,可以先在B站找一下视频看一下

没有解决我的问题,去提问