文章采集api
監視系統選擇,必須閱讀本文
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 200 次瀏覽 ? 2020-08-06 18:15
[為什么要學(xué)習爬網(wǎng)? 】1.爬網(wǎng)程序易于入門(mén),但難以深入. 如何編寫(xiě)高效的采集器,如何編寫(xiě)高度靈活和可伸縮的采集器是一項技術(shù)任務(wù). 此外,在爬網(wǎng)過(guò)程中,經(jīng)常容易遇到反爬蟲(chóng),例如字體防爬網(wǎng),IP識別,驗證碼等. 如何克服困難并獲得所需的數據,您可以學(xué)習此課程! 2.如果您是其他行業(yè)的開(kāi)發(fā)人員,例如應用程序開(kāi)發(fā),網(wǎng)站開(kāi)發(fā),那么學(xué)習爬蟲(chóng)程序可以增強您的技術(shù)知識,并開(kāi)發(fā)更安全的軟件和網(wǎng)站[課程設計]完整的爬蟲(chóng)程序,無(wú)論大小,它可以分為三個(gè)步驟,即: 網(wǎng)絡(luò )請求: 模擬瀏覽器的行為以從Internet抓取數據. 數據分析: 過(guò)濾請求的數據并提取所需的數據. 數據存儲: 將提取的數據存儲到硬盤(pán)或內存中. 例如,使用mysql數據庫或redis. 然后按照這些步驟逐步解釋本課程,使學(xué)生充分掌握每個(gè)步驟的技術(shù). 另外,由于爬行器的多樣性,在爬行過(guò)程中可能會(huì )發(fā)生反爬行和低效率的情況. 因此,我們增加了兩章來(lái)提高采集器程序的靈活性. 它們是: 高級采集器: 包括IP代理,多線(xiàn)程采集器,圖形驗證碼識別,JS加密和解密,動(dòng)態(tài)Web采集器,字體反搜尋識別等. Scrapy和分布式爬蟲(chóng): Scrapy框架,Scrapy-redis組件,分布式爬蟲(chóng)等. 我們可以通過(guò)爬蟲(chóng)的高級知識點(diǎn)來(lái)處理大量反爬蟲(chóng)網(wǎng)站,并且Scrapy框架是使用它的專(zhuān)業(yè)爬蟲(chóng)框架可以快速提高我們的抓取程序的效率和速度. 此外,如果一臺計算機無(wú)法滿(mǎn)足您的需求,我們可以使用分布式爬網(wǎng)程序讓多臺計算機幫助您快速爬網(wǎng)數據. 從基本的采集器到商業(yè)應用程序采集器,這套課程都可以滿(mǎn)足您的所有需求! [課程服務(wù)]獨家付費社區+每個(gè)星期三的討論會(huì )+ 1v1問(wèn)答 查看全部
[為什么要學(xué)習爬網(wǎng)? 】1.爬網(wǎng)程序易于入門(mén),但難以深入. 如何編寫(xiě)高效的采集器,如何編寫(xiě)高度靈活和可伸縮的采集器是一項技術(shù)任務(wù). 此外,在爬網(wǎng)過(guò)程中,經(jīng)常容易遇到反爬蟲(chóng),例如字體防爬網(wǎng),IP識別,驗證碼等. 如何克服困難并獲得所需的數據,您可以學(xué)習此課程! 2.如果您是其他行業(yè)的開(kāi)發(fā)人員,例如應用程序開(kāi)發(fā),網(wǎng)站開(kāi)發(fā),那么學(xué)習爬蟲(chóng)程序可以增強您的技術(shù)知識,并開(kāi)發(fā)更安全的軟件和網(wǎng)站[課程設計]完整的爬蟲(chóng)程序,無(wú)論大小,它可以分為三個(gè)步驟,即: 網(wǎng)絡(luò )請求: 模擬瀏覽器的行為以從Internet抓取數據. 數據分析: 過(guò)濾請求的數據并提取所需的數據. 數據存儲: 將提取的數據存儲到硬盤(pán)或內存中. 例如,使用mysql數據庫或redis. 然后按照這些步驟逐步解釋本課程,使學(xué)生充分掌握每個(gè)步驟的技術(shù). 另外,由于爬行器的多樣性,在爬行過(guò)程中可能會(huì )發(fā)生反爬行和低效率的情況. 因此,我們增加了兩章來(lái)提高采集器程序的靈活性. 它們是: 高級采集器: 包括IP代理,多線(xiàn)程采集器,圖形驗證碼識別,JS加密和解密,動(dòng)態(tài)Web采集器,字體反搜尋識別等. Scrapy和分布式爬蟲(chóng): Scrapy框架,Scrapy-redis組件,分布式爬蟲(chóng)等. 我們可以通過(guò)爬蟲(chóng)的高級知識點(diǎn)來(lái)處理大量反爬蟲(chóng)網(wǎng)站,并且Scrapy框架是使用它的專(zhuān)業(yè)爬蟲(chóng)框架可以快速提高我們的抓取程序的效率和速度. 此外,如果一臺計算機無(wú)法滿(mǎn)足您的需求,我們可以使用分布式爬網(wǎng)程序讓多臺計算機幫助您快速爬網(wǎng)數據. 從基本的采集器到商業(yè)應用程序采集器,這套課程都可以滿(mǎn)足您的所有需求! [課程服務(wù)]獨家付費社區+每個(gè)星期三的討論會(huì )+ 1v1問(wèn)答
視頻捕獲: 基于Camera 2實(shí)現的Android平臺
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 193 次瀏覽 ? 2020-08-06 15:09
前言
本文簡(jiǎn)要介紹了如何使用Camera2相關(guān)API在移動(dòng)Android系統下進(jìn)行視頻捕獲.
Camera2是Google添加到Android 5.0中的全新API,以代替Camera1來(lái)操作相機.
按照慣例,源代碼AndroidVideo是第一位.
Camera2調用相機捕獲視頻的核心實(shí)現是在Camera2Capture.java中.
權限配置
要使用Android平臺提供的攝像頭,必須首先在配置文件中添加以下權限配置:
獲取相機信息
打開(kāi)相機管理器
CameraManager是用于檢測,連接和描述相機設備的系統服務(wù). 您可以通過(guò)調用Context.getSystemService(java.lang.String)方法獲取CameraManager的實(shí)例:
CameraManager mManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
獲取相機列表信息
通過(guò)調用CameraManager.getCameraIdList()方法,可以獲得攝像機ID的列表:
String[] cameraIds = mCameraManager.getCameraIdList();
for (String id : cameraIds) {
//TODO
}
可以通過(guò)相應的ID從CameraManager獲取相應攝像機的屬性集CameraCharacteristics.
在CameraCharacteristics中,您可以獲得諸如前后條件,支持的輸出尺寸,支持的輸出格式等信息.
for (String id : cameraIds) {
//傳入攝像頭id,獲取對應攝像頭的參數集
CameraCharacteristics characteristics = mManager.getCameraCharacteristics(id);
//獲取攝像頭的支持等級
Integer level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
//如果是LEGACY等級,不建議使用該攝像頭
if (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
{
continue;
}
//獲取攝像頭的朝向
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
//篩選出前置攝像頭
if (facing != CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
//StreamConfigurationMap包含了該攝像頭支持的size、format等信息
StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//獲取輸出格式為YUV_420_888時(shí)兼容的size
Size[] size = map.getOutputSizes(ImageFormat.YUV_420_888);
//獲取輸出View為SurfaceView時(shí)兼容的size
//Size[] size = map.getOutputSizes(SurfaceHolder.class);
//TODO 其他的參數,例如輸出格式、輸出幀率上下限等
}
PS: 對于Camera2采集系統,每個(gè)攝像機都有一個(gè)支持級別:
PS: 通常,如果攝像機級別為L(cháng)EVEL_3和LEVEL_FULL,建議使用Camera2進(jìn)行采集,否則建議使用具有更好兼容性的Camera1進(jìn)行視頻采集.
打開(kāi)相機
通過(guò)攝像機信息,我們可以找到所需的CameraId,然后使用該ID來(lái)獲取我們的攝像機設備CameraDevice.
函數原型是public void openCamera(String cameraId,final CameraDevice.StateCallback回調,Handler handler),
cameraId是需要打開(kāi)的攝像機的ID. 為了監視攝像機的情況,您需要傳遞一個(gè)回調,這是第二個(gè)參數CameraDevice.StateCallback. 當然,如果我們不希望打開(kāi)操作占用UI線(xiàn)程時(shí)間,
我們可以使用Looper構造HandlerThread子線(xiàn)程,然后傳入Handler.
//打開(kāi)攝像頭,正常打開(kāi)會(huì )回調到CameraDeviceStateCallback的onOpened方法
mManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
//攝像頭成功連接
//camera也就是我們需要獲取的攝像頭設備
mCameraDevice = camera;
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
//攝像頭斷開(kāi)連接
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
//打開(kāi)錯誤
}
}, mHandler);
創(chuàng )建一個(gè)采集會(huì )話(huà)
成功打開(kāi)相機并獲取相應的CameraDevice之后,我們需要創(chuàng )建一個(gè)采集會(huì )話(huà)以提供程序與相機之間的通信.
函數原型是公共抽象void createCaptureSession(列表輸出,CameraCaptureSession.StateCallback回調,Handler處理程序)引發(fā)CameraAccessException.
傳入的第一個(gè)參數是需要采集的Surface. 為了監視會(huì )話(huà)的創(chuàng )建,我們需要傳遞CameraCaptureSession.StateCallback回調. 當然,第三個(gè)參數是允許在相應的Handler所在的線(xiàn)程中執行操作.
//獲取一個(gè)采集Session會(huì )話(huà),正常流程回回調到CameraCaptureSessionStateCallback的onConfigured方法
mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceView.getHolder().getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建成功
//mCameraCaptureSession也就是新創(chuàng )建的會(huì )話(huà)
mCameraCaptureSession = session;
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建失敗
}
}, mHandler);
PS: 對于某些業(yè)務(wù)需求,有必要提高捕獲幀速率(120fps及以上). 這個(gè)createConstrainedHighSpeedCaptureSession()會(huì )話(huà)可以很好地支持此功能.
發(fā)送采集請求
當您需要開(kāi)始采集時(shí),需要構造一個(gè)采集請求,然后將該請求發(fā)送到采集會(huì )話(huà).
//創(chuàng )建一個(gè)基于錄制的請求
mRequest = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
//將需要的目標Surface加入Target列表
mRequest.addTarget(surface);
//重復發(fā)送這個(gè)請求,進(jìn)行持續的采集
mCameraCaptureSession.setRepeatingRequest(mRequest.build(), NULL, mHandler);
原創(chuàng )數據回調
在獲取Camera1時(shí),通常通過(guò)設置setPreviewCallbackWithBuffer()和addCallbackBuffer()來(lái)獲取采集的原創(chuàng )數據,那么該功能如何在Camera2中實(shí)現?
我們可以使用ImageReader類(lèi):
//ImageReader是一個(gè)數據回調模塊,類(lèi)似于Camera1的setPreviewCallbackWithBuffer
mReader = ImageReader.newInstance(mConfig.mWidth, mConfig.mHeight, mConfig.mFormat, 2);
mReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
//數據處理
image.close();
}
}, mHandler);
我們需要在createCaptureSession()的第一個(gè)參數中傳遞ImageReader的Surface:
//通過(guò)ImageReader.getSurface()獲取一個(gè)Surface并將其傳給Session中
mCameraDevice.createCaptureSession(Arrays.asList(mReader.getSurface())//....);
然后將這個(gè)目標添加到CaptureRequest中:
//當然,構造請求時(shí),需要將該Surface同時(shí)加入到Request的Target列表中
mRequest.addTarget(mReader.getSurface());
參考資料
對于Camera2相關(guān)的項目,我們通??梢詤⒖家韵马椖?
googlesamples / android-Camera2Basic
google / cameraview
結論
本文簡(jiǎn)要介紹了基于Camera2 API的Android平臺的相機采集功能.
盡管Camera2是Google推薦的當前采集框架,但是由于制造商的兼容性問(wèn)題,Camera2的API功能相對不穩定;
因此,作者仍然建議開(kāi)發(fā)以Camera1作為主要集合,而Camera2作為輔助集合的體系結構. 查看全部
本文簡(jiǎn)要介紹了如何使用Camera2相關(guān)API在移動(dòng)Android系統下進(jìn)行視頻捕獲.
Camera2是Google添加到Android 5.0中的全新API,以代替Camera1來(lái)操作相機.
按照慣例,源代碼AndroidVideo是第一位.
Camera2調用相機捕獲視頻的核心實(shí)現是在Camera2Capture.java中.
權限配置
要使用Android平臺提供的攝像頭,必須首先在配置文件中添加以下權限配置:
獲取相機信息
打開(kāi)相機管理器
CameraManager是用于檢測,連接和描述相機設備的系統服務(wù). 您可以通過(guò)調用Context.getSystemService(java.lang.String)方法獲取CameraManager的實(shí)例:
CameraManager mManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
獲取相機列表信息
通過(guò)調用CameraManager.getCameraIdList()方法,可以獲得攝像機ID的列表:
String[] cameraIds = mCameraManager.getCameraIdList();
for (String id : cameraIds) {
//TODO
}
可以通過(guò)相應的ID從CameraManager獲取相應攝像機的屬性集CameraCharacteristics.
在CameraCharacteristics中,您可以獲得諸如前后條件,支持的輸出尺寸,支持的輸出格式等信息.
for (String id : cameraIds) {
//傳入攝像頭id,獲取對應攝像頭的參數集
CameraCharacteristics characteristics = mManager.getCameraCharacteristics(id);
//獲取攝像頭的支持等級
Integer level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
//如果是LEGACY等級,不建議使用該攝像頭
if (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
{
continue;
}
//獲取攝像頭的朝向
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
//篩選出前置攝像頭
if (facing != CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
//StreamConfigurationMap包含了該攝像頭支持的size、format等信息
StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//獲取輸出格式為YUV_420_888時(shí)兼容的size
Size[] size = map.getOutputSizes(ImageFormat.YUV_420_888);
//獲取輸出View為SurfaceView時(shí)兼容的size
//Size[] size = map.getOutputSizes(SurfaceHolder.class);
//TODO 其他的參數,例如輸出格式、輸出幀率上下限等
}
PS: 對于Camera2采集系統,每個(gè)攝像機都有一個(gè)支持級別:
PS: 通常,如果攝像機級別為L(cháng)EVEL_3和LEVEL_FULL,建議使用Camera2進(jìn)行采集,否則建議使用具有更好兼容性的Camera1進(jìn)行視頻采集.
打開(kāi)相機
通過(guò)攝像機信息,我們可以找到所需的CameraId,然后使用該ID來(lái)獲取我們的攝像機設備CameraDevice.
函數原型是public void openCamera(String cameraId,final CameraDevice.StateCallback回調,Handler handler),
cameraId是需要打開(kāi)的攝像機的ID. 為了監視攝像機的情況,您需要傳遞一個(gè)回調,這是第二個(gè)參數CameraDevice.StateCallback. 當然,如果我們不希望打開(kāi)操作占用UI線(xiàn)程時(shí)間,
我們可以使用Looper構造HandlerThread子線(xiàn)程,然后傳入Handler.
//打開(kāi)攝像頭,正常打開(kāi)會(huì )回調到CameraDeviceStateCallback的onOpened方法
mManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
//攝像頭成功連接
//camera也就是我們需要獲取的攝像頭設備
mCameraDevice = camera;
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
//攝像頭斷開(kāi)連接
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
//打開(kāi)錯誤
}
}, mHandler);
創(chuàng )建一個(gè)采集會(huì )話(huà)
成功打開(kāi)相機并獲取相應的CameraDevice之后,我們需要創(chuàng )建一個(gè)采集會(huì )話(huà)以提供程序與相機之間的通信.
函數原型是公共抽象void createCaptureSession(列表輸出,CameraCaptureSession.StateCallback回調,Handler處理程序)引發(fā)CameraAccessException.
傳入的第一個(gè)參數是需要采集的Surface. 為了監視會(huì )話(huà)的創(chuàng )建,我們需要傳遞CameraCaptureSession.StateCallback回調. 當然,第三個(gè)參數是允許在相應的Handler所在的線(xiàn)程中執行操作.
//獲取一個(gè)采集Session會(huì )話(huà),正常流程回回調到CameraCaptureSessionStateCallback的onConfigured方法
mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceView.getHolder().getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建成功
//mCameraCaptureSession也就是新創(chuàng )建的會(huì )話(huà)
mCameraCaptureSession = session;
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建失敗
}
}, mHandler);
PS: 對于某些業(yè)務(wù)需求,有必要提高捕獲幀速率(120fps及以上). 這個(gè)createConstrainedHighSpeedCaptureSession()會(huì )話(huà)可以很好地支持此功能.
發(fā)送采集請求
當您需要開(kāi)始采集時(shí),需要構造一個(gè)采集請求,然后將該請求發(fā)送到采集會(huì )話(huà).
//創(chuàng )建一個(gè)基于錄制的請求
mRequest = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
//將需要的目標Surface加入Target列表
mRequest.addTarget(surface);
//重復發(fā)送這個(gè)請求,進(jìn)行持續的采集
mCameraCaptureSession.setRepeatingRequest(mRequest.build(), NULL, mHandler);
原創(chuàng )數據回調
在獲取Camera1時(shí),通常通過(guò)設置setPreviewCallbackWithBuffer()和addCallbackBuffer()來(lái)獲取采集的原創(chuàng )數據,那么該功能如何在Camera2中實(shí)現?
我們可以使用ImageReader類(lèi):
//ImageReader是一個(gè)數據回調模塊,類(lèi)似于Camera1的setPreviewCallbackWithBuffer
mReader = ImageReader.newInstance(mConfig.mWidth, mConfig.mHeight, mConfig.mFormat, 2);
mReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
//數據處理
image.close();
}
}, mHandler);
我們需要在createCaptureSession()的第一個(gè)參數中傳遞ImageReader的Surface:
//通過(guò)ImageReader.getSurface()獲取一個(gè)Surface并將其傳給Session中
mCameraDevice.createCaptureSession(Arrays.asList(mReader.getSurface())//....);
然后將這個(gè)目標添加到CaptureRequest中:
//當然,構造請求時(shí),需要將該Surface同時(shí)加入到Request的Target列表中
mRequest.addTarget(mReader.getSurface());
參考資料
對于Camera2相關(guān)的項目,我們通??梢詤⒖家韵马椖?
googlesamples / android-Camera2Basic
google / cameraview
結論
本文簡(jiǎn)要介紹了基于Camera2 API的Android平臺的相機采集功能.
盡管Camera2是Google推薦的當前采集框架,但是由于制造商的兼容性問(wèn)題,Camera2的API功能相對不穩定;
因此,作者仍然建議開(kāi)發(fā)以Camera1作為主要集合,而Camera2作為輔助集合的體系結構. 查看全部
前言
本文簡(jiǎn)要介紹了如何使用Camera2相關(guān)API在移動(dòng)Android系統下進(jìn)行視頻捕獲.
Camera2是Google添加到Android 5.0中的全新API,以代替Camera1來(lái)操作相機.
按照慣例,源代碼AndroidVideo是第一位.
Camera2調用相機捕獲視頻的核心實(shí)現是在Camera2Capture.java中.
權限配置
要使用Android平臺提供的攝像頭,必須首先在配置文件中添加以下權限配置:
獲取相機信息
打開(kāi)相機管理器
CameraManager是用于檢測,連接和描述相機設備的系統服務(wù). 您可以通過(guò)調用Context.getSystemService(java.lang.String)方法獲取CameraManager的實(shí)例:
CameraManager mManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
獲取相機列表信息
通過(guò)調用CameraManager.getCameraIdList()方法,可以獲得攝像機ID的列表:
String[] cameraIds = mCameraManager.getCameraIdList();
for (String id : cameraIds) {
//TODO
}
可以通過(guò)相應的ID從CameraManager獲取相應攝像機的屬性集CameraCharacteristics.
在CameraCharacteristics中,您可以獲得諸如前后條件,支持的輸出尺寸,支持的輸出格式等信息.
for (String id : cameraIds) {
//傳入攝像頭id,獲取對應攝像頭的參數集
CameraCharacteristics characteristics = mManager.getCameraCharacteristics(id);
//獲取攝像頭的支持等級
Integer level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
//如果是LEGACY等級,不建議使用該攝像頭
if (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
{
continue;
}
//獲取攝像頭的朝向
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
//篩選出前置攝像頭
if (facing != CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
//StreamConfigurationMap包含了該攝像頭支持的size、format等信息
StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//獲取輸出格式為YUV_420_888時(shí)兼容的size
Size[] size = map.getOutputSizes(ImageFormat.YUV_420_888);
//獲取輸出View為SurfaceView時(shí)兼容的size
//Size[] size = map.getOutputSizes(SurfaceHolder.class);
//TODO 其他的參數,例如輸出格式、輸出幀率上下限等
}
PS: 對于Camera2采集系統,每個(gè)攝像機都有一個(gè)支持級別:
PS: 通常,如果攝像機級別為L(cháng)EVEL_3和LEVEL_FULL,建議使用Camera2進(jìn)行采集,否則建議使用具有更好兼容性的Camera1進(jìn)行視頻采集.
打開(kāi)相機
通過(guò)攝像機信息,我們可以找到所需的CameraId,然后使用該ID來(lái)獲取我們的攝像機設備CameraDevice.
函數原型是public void openCamera(String cameraId,final CameraDevice.StateCallback回調,Handler handler),
cameraId是需要打開(kāi)的攝像機的ID. 為了監視攝像機的情況,您需要傳遞一個(gè)回調,這是第二個(gè)參數CameraDevice.StateCallback. 當然,如果我們不希望打開(kāi)操作占用UI線(xiàn)程時(shí)間,
我們可以使用Looper構造HandlerThread子線(xiàn)程,然后傳入Handler.
//打開(kāi)攝像頭,正常打開(kāi)會(huì )回調到CameraDeviceStateCallback的onOpened方法
mManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
//攝像頭成功連接
//camera也就是我們需要獲取的攝像頭設備
mCameraDevice = camera;
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
//攝像頭斷開(kāi)連接
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
//打開(kāi)錯誤
}
}, mHandler);
創(chuàng )建一個(gè)采集會(huì )話(huà)
成功打開(kāi)相機并獲取相應的CameraDevice之后,我們需要創(chuàng )建一個(gè)采集會(huì )話(huà)以提供程序與相機之間的通信.
函數原型是公共抽象void createCaptureSession(列表輸出,CameraCaptureSession.StateCallback回調,Handler處理程序)引發(fā)CameraAccessException.
傳入的第一個(gè)參數是需要采集的Surface. 為了監視會(huì )話(huà)的創(chuàng )建,我們需要傳遞CameraCaptureSession.StateCallback回調. 當然,第三個(gè)參數是允許在相應的Handler所在的線(xiàn)程中執行操作.
//獲取一個(gè)采集Session會(huì )話(huà),正常流程回回調到CameraCaptureSessionStateCallback的onConfigured方法
mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceView.getHolder().getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建成功
//mCameraCaptureSession也就是新創(chuàng )建的會(huì )話(huà)
mCameraCaptureSession = session;
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建失敗
}
}, mHandler);
PS: 對于某些業(yè)務(wù)需求,有必要提高捕獲幀速率(120fps及以上). 這個(gè)createConstrainedHighSpeedCaptureSession()會(huì )話(huà)可以很好地支持此功能.
發(fā)送采集請求
當您需要開(kāi)始采集時(shí),需要構造一個(gè)采集請求,然后將該請求發(fā)送到采集會(huì )話(huà).
//創(chuàng )建一個(gè)基于錄制的請求
mRequest = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
//將需要的目標Surface加入Target列表
mRequest.addTarget(surface);
//重復發(fā)送這個(gè)請求,進(jìn)行持續的采集
mCameraCaptureSession.setRepeatingRequest(mRequest.build(), NULL, mHandler);
原創(chuàng )數據回調
在獲取Camera1時(shí),通常通過(guò)設置setPreviewCallbackWithBuffer()和addCallbackBuffer()來(lái)獲取采集的原創(chuàng )數據,那么該功能如何在Camera2中實(shí)現?
我們可以使用ImageReader類(lèi):
//ImageReader是一個(gè)數據回調模塊,類(lèi)似于Camera1的setPreviewCallbackWithBuffer
mReader = ImageReader.newInstance(mConfig.mWidth, mConfig.mHeight, mConfig.mFormat, 2);
mReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
//數據處理
image.close();
}
}, mHandler);
我們需要在createCaptureSession()的第一個(gè)參數中傳遞ImageReader的Surface:
//通過(guò)ImageReader.getSurface()獲取一個(gè)Surface并將其傳給Session中
mCameraDevice.createCaptureSession(Arrays.asList(mReader.getSurface())//....);
然后將這個(gè)目標添加到CaptureRequest中:
//當然,構造請求時(shí),需要將該Surface同時(shí)加入到Request的Target列表中
mRequest.addTarget(mReader.getSurface());
參考資料
對于Camera2相關(guān)的項目,我們通??梢詤⒖家韵马椖?
googlesamples / android-Camera2Basic
google / cameraview
結論
本文簡(jiǎn)要介紹了基于Camera2 API的Android平臺的相機采集功能.
盡管Camera2是Google推薦的當前采集框架,但是由于制造商的兼容性問(wèn)題,Camera2的API功能相對不穩定;
因此,作者仍然建議開(kāi)發(fā)以Camera1作為主要集合,而Camera2作為輔助集合的體系結構.
PHP+fiddler抓包采集微信文章閱讀數點(diǎn)贊數的思路解讀
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 378 次瀏覽 ? 2020-08-04 09:00
更新時(shí)間:2019年12月20日 10:02:43 轉載作者:flysnownet
這篇文章主要介紹了PHP+fiddler抓包采集微信文章閱讀數點(diǎn)贊數的思路,非常不錯,具有一定的參考借鑒價(jià)值,需要的同學(xué)可以參考下
簡(jiǎn)介:
分析插口曉得要獲取文章閱讀數和點(diǎn)贊數必須有key和uin這兩個(gè)關(guān)鍵參數文章采集api,不同公眾號key不一樣(據說(shuō)有萬(wàn)能陌陌key,不懂如何搞到)文章采集api,同一個(gè)公眾號key大約半小時(shí)會(huì )過(guò)期
提交鏈接獲取文章閱讀量api
思路:
1.將客戶(hù)端懇求閱讀量插口的懇求攔截轉發(fā)到自己服務(wù)器,這樣就可以獲取到key ,用__biz關(guān)聯(lián)緩存半小時(shí)
2.提交文章鏈接進(jìn)行查詢(xún)時(shí),服務(wù)器從文章鏈接里獲取__biz,查詢(xún)是否緩存了當前公眾號對應的key,有的話(huà)進(jìn)行第3步,沒(méi)有進(jìn)行第4步。
3.curl懇求 接口獲取數據
4.key不存在時(shí),通知客戶(hù)端重定向到該url(通知用websocket通知或則客戶(hù)端ajax協(xié)程,需要用抓包工具更改文章詳情頁(yè)代碼使其跳轉到中間頁(yè)面待命,打開(kāi)文章頁(yè)面后隔幾秒挪到中間頁(yè))并暫停程序幾秒等待客戶(hù)端更新key,此時(shí)客戶(hù)端遞交了新的key,用其進(jìn)行查詢(xún)
實(shí)現
1.抓包
此插口就是獲取閱讀量的插口,參數如下圖
2.將此插口攔截轉發(fā)到自己服務(wù)器,點(diǎn)擊 rules- customize rules 在OnBeforeRequest(正式懇求之前執行的函數)加上
if (oSession.fullUrl.Contains("mp.weixin.qq.com/mp/getappmsgext"))
{
oSession.oRequest["Host"]= 'ccc.aaa.com' ;
}
效果,可以見(jiàn)到此插口早已被轉發(fā)
3.服務(wù)端緩存key,代碼以PHP為例
public function saveKey(Request $request)
{
$__biz = $request->param('__biz',0);
$data['uin'] = $request->param('uin',0);
$data['key'] = $request->param('key',0);
Cache::set($__biz,$data,30 * 60);
return 'ok';
}
4.提交文章鏈接查詢(xún)API代碼
public function getReadNum(Request $request)
{
$url = $request->param('url');
parse_str(parse_url($url)['query'], $param);
$__biz = $param['__biz'];
$key_data = Cache::get($__biz);
if (empty($key_data))
return 'no key';
$uin = $key_data['uin'];
$key = $key_data['key'];
$param['uin'] = $uin;
$param['key'] = $key;
$param['wxtoken'] = "777";
$wechat_url = "https://mp.weixin.qq.com/mp/getappmsgext?" . http_build_query($param);
//dump($wechat_url);
$data = array(
'is_only_read' => 1,
'is_temp_url' => 0,
'appmsg_type' => 9,
);
$res = $this->get_url($wechat_url,$data);
return $res;
}
function get_url($url,$data)
{
$ifpost = 1;//是否post請求
$datafields = $data;//post數據
$cookiefile = '';//cookie文件
$cookie = '';//cookie變量
$v = false;
//模擬http請求header頭
$header = array("Connection: Keep-Alive","Accept: text/html, application/xhtml+xml, */*", "Pragma: no-cache", "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3","User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1278.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.5 WindowsWechat");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, $v);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$ifpost && curl_setopt($ch, CURLOPT_POST, $ifpost);
$ifpost && curl_setopt($ch, CURLOPT_POSTFIELDS, $datafields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$cookie && curl_setopt($ch, CURLOPT_COOKIE, $cookie);//發(fā)送cookie變量
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);//發(fā)送cookie文件
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile);//寫(xiě)入cookie到文件
curl_setopt($ch,CURLOPT_TIMEOUT,60); //允許執行的最長(cháng)秒數
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$ok = curl_exec($ch);
curl_close($ch);
unset($ch);
return $ok;
}
5.通知客戶(hù)端重定向頁(yè)面(這部份沒(méi)寫(xiě),看參考我的其他關(guān)于文本socket文章)
6.用fiddler更改陌陌文章也jsj腳本,
在OnBeforeResponse(返回給客戶(hù)端之前執行的方式),加上跳轉到中間頁(yè)的代碼
效果
總結 查看全部
這篇文章主要介紹了PHP+fiddler抓包采集微信文章閱讀數點(diǎn)贊數的思路,非常不錯,具有一定的參考借鑒價(jià)值,需要的同學(xué)可以參考下
簡(jiǎn)介:
分析插口曉得要獲取文章閱讀數和點(diǎn)贊數必須有key和uin這兩個(gè)關(guān)鍵參數文章采集api,不同公眾號key不一樣(據說(shuō)有萬(wàn)能陌陌key,不懂如何搞到)文章采集api,同一個(gè)公眾號key大約半小時(shí)會(huì )過(guò)期
提交鏈接獲取文章閱讀量api
思路:
1.將客戶(hù)端懇求閱讀量插口的懇求攔截轉發(fā)到自己服務(wù)器,這樣就可以獲取到key ,用__biz關(guān)聯(lián)緩存半小時(shí)
2.提交文章鏈接進(jìn)行查詢(xún)時(shí),服務(wù)器從文章鏈接里獲取__biz,查詢(xún)是否緩存了當前公眾號對應的key,有的話(huà)進(jìn)行第3步,沒(méi)有進(jìn)行第4步。
3.curl懇求 接口獲取數據
4.key不存在時(shí),通知客戶(hù)端重定向到該url(通知用websocket通知或則客戶(hù)端ajax協(xié)程,需要用抓包工具更改文章詳情頁(yè)代碼使其跳轉到中間頁(yè)面待命,打開(kāi)文章頁(yè)面后隔幾秒挪到中間頁(yè))并暫停程序幾秒等待客戶(hù)端更新key,此時(shí)客戶(hù)端遞交了新的key,用其進(jìn)行查詢(xún)
實(shí)現
1.抓包
此插口就是獲取閱讀量的插口,參數如下圖
2.將此插口攔截轉發(fā)到自己服務(wù)器,點(diǎn)擊 rules- customize rules 在OnBeforeRequest(正式懇求之前執行的函數)加上
if (oSession.fullUrl.Contains("mp.weixin.qq.com/mp/getappmsgext"))
{
oSession.oRequest["Host"]= 'ccc.aaa.com' ;
}
效果,可以見(jiàn)到此插口早已被轉發(fā)
3.服務(wù)端緩存key,代碼以PHP為例
public function saveKey(Request $request)
{
$__biz = $request->param('__biz',0);
$data['uin'] = $request->param('uin',0);
$data['key'] = $request->param('key',0);
Cache::set($__biz,$data,30 * 60);
return 'ok';
}
4.提交文章鏈接查詢(xún)API代碼
public function getReadNum(Request $request)
{
$url = $request->param('url');
parse_str(parse_url($url)['query'], $param);
$__biz = $param['__biz'];
$key_data = Cache::get($__biz);
if (empty($key_data))
return 'no key';
$uin = $key_data['uin'];
$key = $key_data['key'];
$param['uin'] = $uin;
$param['key'] = $key;
$param['wxtoken'] = "777";
$wechat_url = "https://mp.weixin.qq.com/mp/getappmsgext?" . http_build_query($param);
//dump($wechat_url);
$data = array(
'is_only_read' => 1,
'is_temp_url' => 0,
'appmsg_type' => 9,
);
$res = $this->get_url($wechat_url,$data);
return $res;
}
function get_url($url,$data)
{
$ifpost = 1;//是否post請求
$datafields = $data;//post數據
$cookiefile = '';//cookie文件
$cookie = '';//cookie變量
$v = false;
//模擬http請求header頭
$header = array("Connection: Keep-Alive","Accept: text/html, application/xhtml+xml, */*", "Pragma: no-cache", "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3","User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1278.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.5 WindowsWechat");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, $v);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$ifpost && curl_setopt($ch, CURLOPT_POST, $ifpost);
$ifpost && curl_setopt($ch, CURLOPT_POSTFIELDS, $datafields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$cookie && curl_setopt($ch, CURLOPT_COOKIE, $cookie);//發(fā)送cookie變量
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);//發(fā)送cookie文件
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile);//寫(xiě)入cookie到文件
curl_setopt($ch,CURLOPT_TIMEOUT,60); //允許執行的最長(cháng)秒數
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$ok = curl_exec($ch);
curl_close($ch);
unset($ch);
return $ok;
}
5.通知客戶(hù)端重定向頁(yè)面(這部份沒(méi)寫(xiě),看參考我的其他關(guān)于文本socket文章)
6.用fiddler更改陌陌文章也jsj腳本,
在OnBeforeResponse(返回給客戶(hù)端之前執行的方式),加上跳轉到中間頁(yè)的代碼
效果
總結 查看全部
更新時(shí)間:2019年12月20日 10:02:43 轉載作者:flysnownet
這篇文章主要介紹了PHP+fiddler抓包采集微信文章閱讀數點(diǎn)贊數的思路,非常不錯,具有一定的參考借鑒價(jià)值,需要的同學(xué)可以參考下
簡(jiǎn)介:
分析插口曉得要獲取文章閱讀數和點(diǎn)贊數必須有key和uin這兩個(gè)關(guān)鍵參數文章采集api,不同公眾號key不一樣(據說(shuō)有萬(wàn)能陌陌key,不懂如何搞到)文章采集api,同一個(gè)公眾號key大約半小時(shí)會(huì )過(guò)期
提交鏈接獲取文章閱讀量api
思路:
1.將客戶(hù)端懇求閱讀量插口的懇求攔截轉發(fā)到自己服務(wù)器,這樣就可以獲取到key ,用__biz關(guān)聯(lián)緩存半小時(shí)
2.提交文章鏈接進(jìn)行查詢(xún)時(shí),服務(wù)器從文章鏈接里獲取__biz,查詢(xún)是否緩存了當前公眾號對應的key,有的話(huà)進(jìn)行第3步,沒(méi)有進(jìn)行第4步。
3.curl懇求 接口獲取數據
4.key不存在時(shí),通知客戶(hù)端重定向到該url(通知用websocket通知或則客戶(hù)端ajax協(xié)程,需要用抓包工具更改文章詳情頁(yè)代碼使其跳轉到中間頁(yè)面待命,打開(kāi)文章頁(yè)面后隔幾秒挪到中間頁(yè))并暫停程序幾秒等待客戶(hù)端更新key,此時(shí)客戶(hù)端遞交了新的key,用其進(jìn)行查詢(xún)
實(shí)現
1.抓包
此插口就是獲取閱讀量的插口,參數如下圖


2.將此插口攔截轉發(fā)到自己服務(wù)器,點(diǎn)擊 rules- customize rules 在OnBeforeRequest(正式懇求之前執行的函數)加上
if (oSession.fullUrl.Contains("mp.weixin.qq.com/mp/getappmsgext"))
{
oSession.oRequest["Host"]= 'ccc.aaa.com' ;
}

效果,可以見(jiàn)到此插口早已被轉發(fā)

3.服務(wù)端緩存key,代碼以PHP為例
public function saveKey(Request $request)
{
$__biz = $request->param('__biz',0);
$data['uin'] = $request->param('uin',0);
$data['key'] = $request->param('key',0);
Cache::set($__biz,$data,30 * 60);
return 'ok';
}
4.提交文章鏈接查詢(xún)API代碼
public function getReadNum(Request $request)
{
$url = $request->param('url');
parse_str(parse_url($url)['query'], $param);
$__biz = $param['__biz'];
$key_data = Cache::get($__biz);
if (empty($key_data))
return 'no key';
$uin = $key_data['uin'];
$key = $key_data['key'];
$param['uin'] = $uin;
$param['key'] = $key;
$param['wxtoken'] = "777";
$wechat_url = "https://mp.weixin.qq.com/mp/getappmsgext?" . http_build_query($param);
//dump($wechat_url);
$data = array(
'is_only_read' => 1,
'is_temp_url' => 0,
'appmsg_type' => 9,
);
$res = $this->get_url($wechat_url,$data);
return $res;
}
function get_url($url,$data)
{
$ifpost = 1;//是否post請求
$datafields = $data;//post數據
$cookiefile = '';//cookie文件
$cookie = '';//cookie變量
$v = false;
//模擬http請求header頭
$header = array("Connection: Keep-Alive","Accept: text/html, application/xhtml+xml, */*", "Pragma: no-cache", "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3","User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1278.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.5 WindowsWechat");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, $v);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$ifpost && curl_setopt($ch, CURLOPT_POST, $ifpost);
$ifpost && curl_setopt($ch, CURLOPT_POSTFIELDS, $datafields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$cookie && curl_setopt($ch, CURLOPT_COOKIE, $cookie);//發(fā)送cookie變量
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);//發(fā)送cookie文件
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile);//寫(xiě)入cookie到文件
curl_setopt($ch,CURLOPT_TIMEOUT,60); //允許執行的最長(cháng)秒數
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$ok = curl_exec($ch);
curl_close($ch);
unset($ch);
return $ok;
}
5.通知客戶(hù)端重定向頁(yè)面(這部份沒(méi)寫(xiě),看參考我的其他關(guān)于文本socket文章)
6.用fiddler更改陌陌文章也jsj腳本,
在OnBeforeResponse(返回給客戶(hù)端之前執行的方式),加上跳轉到中間頁(yè)的代碼
效果

總結
監視系統選擇,必須閱讀本文
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 200 次瀏覽 ? 2020-08-06 18:15
[為什么要學(xué)習爬網(wǎng)? 】1.爬網(wǎng)程序易于入門(mén),但難以深入. 如何編寫(xiě)高效的采集器,如何編寫(xiě)高度靈活和可伸縮的采集器是一項技術(shù)任務(wù). 此外,在爬網(wǎng)過(guò)程中,經(jīng)常容易遇到反爬蟲(chóng),例如字體防爬網(wǎng),IP識別,驗證碼等. 如何克服困難并獲得所需的數據,您可以學(xué)習此課程! 2.如果您是其他行業(yè)的開(kāi)發(fā)人員,例如應用程序開(kāi)發(fā),網(wǎng)站開(kāi)發(fā),那么學(xué)習爬蟲(chóng)程序可以增強您的技術(shù)知識,并開(kāi)發(fā)更安全的軟件和網(wǎng)站[課程設計]完整的爬蟲(chóng)程序,無(wú)論大小,它可以分為三個(gè)步驟,即: 網(wǎng)絡(luò )請求: 模擬瀏覽器的行為以從Internet抓取數據. 數據分析: 過(guò)濾請求的數據并提取所需的數據. 數據存儲: 將提取的數據存儲到硬盤(pán)或內存中. 例如,使用mysql數據庫或redis. 然后按照這些步驟逐步解釋本課程,使學(xué)生充分掌握每個(gè)步驟的技術(shù). 另外,由于爬行器的多樣性,在爬行過(guò)程中可能會(huì )發(fā)生反爬行和低效率的情況. 因此,我們增加了兩章來(lái)提高采集器程序的靈活性. 它們是: 高級采集器: 包括IP代理,多線(xiàn)程采集器,圖形驗證碼識別,JS加密和解密,動(dòng)態(tài)Web采集器,字體反搜尋識別等. Scrapy和分布式爬蟲(chóng): Scrapy框架,Scrapy-redis組件,分布式爬蟲(chóng)等. 我們可以通過(guò)爬蟲(chóng)的高級知識點(diǎn)來(lái)處理大量反爬蟲(chóng)網(wǎng)站,并且Scrapy框架是使用它的專(zhuān)業(yè)爬蟲(chóng)框架可以快速提高我們的抓取程序的效率和速度. 此外,如果一臺計算機無(wú)法滿(mǎn)足您的需求,我們可以使用分布式爬網(wǎng)程序讓多臺計算機幫助您快速爬網(wǎng)數據. 從基本的采集器到商業(yè)應用程序采集器,這套課程都可以滿(mǎn)足您的所有需求! [課程服務(wù)]獨家付費社區+每個(gè)星期三的討論會(huì )+ 1v1問(wèn)答 查看全部
[為什么要學(xué)習爬網(wǎng)? 】1.爬網(wǎng)程序易于入門(mén),但難以深入. 如何編寫(xiě)高效的采集器,如何編寫(xiě)高度靈活和可伸縮的采集器是一項技術(shù)任務(wù). 此外,在爬網(wǎng)過(guò)程中,經(jīng)常容易遇到反爬蟲(chóng),例如字體防爬網(wǎng),IP識別,驗證碼等. 如何克服困難并獲得所需的數據,您可以學(xué)習此課程! 2.如果您是其他行業(yè)的開(kāi)發(fā)人員,例如應用程序開(kāi)發(fā),網(wǎng)站開(kāi)發(fā),那么學(xué)習爬蟲(chóng)程序可以增強您的技術(shù)知識,并開(kāi)發(fā)更安全的軟件和網(wǎng)站[課程設計]完整的爬蟲(chóng)程序,無(wú)論大小,它可以分為三個(gè)步驟,即: 網(wǎng)絡(luò )請求: 模擬瀏覽器的行為以從Internet抓取數據. 數據分析: 過(guò)濾請求的數據并提取所需的數據. 數據存儲: 將提取的數據存儲到硬盤(pán)或內存中. 例如,使用mysql數據庫或redis. 然后按照這些步驟逐步解釋本課程,使學(xué)生充分掌握每個(gè)步驟的技術(shù). 另外,由于爬行器的多樣性,在爬行過(guò)程中可能會(huì )發(fā)生反爬行和低效率的情況. 因此,我們增加了兩章來(lái)提高采集器程序的靈活性. 它們是: 高級采集器: 包括IP代理,多線(xiàn)程采集器,圖形驗證碼識別,JS加密和解密,動(dòng)態(tài)Web采集器,字體反搜尋識別等. Scrapy和分布式爬蟲(chóng): Scrapy框架,Scrapy-redis組件,分布式爬蟲(chóng)等. 我們可以通過(guò)爬蟲(chóng)的高級知識點(diǎn)來(lái)處理大量反爬蟲(chóng)網(wǎng)站,并且Scrapy框架是使用它的專(zhuān)業(yè)爬蟲(chóng)框架可以快速提高我們的抓取程序的效率和速度. 此外,如果一臺計算機無(wú)法滿(mǎn)足您的需求,我們可以使用分布式爬網(wǎng)程序讓多臺計算機幫助您快速爬網(wǎng)數據. 從基本的采集器到商業(yè)應用程序采集器,這套課程都可以滿(mǎn)足您的所有需求! [課程服務(wù)]獨家付費社區+每個(gè)星期三的討論會(huì )+ 1v1問(wèn)答
視頻捕獲: 基于Camera 2實(shí)現的Android平臺
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 193 次瀏覽 ? 2020-08-06 15:09
前言
本文簡(jiǎn)要介紹了如何使用Camera2相關(guān)API在移動(dòng)Android系統下進(jìn)行視頻捕獲.
Camera2是Google添加到Android 5.0中的全新API,以代替Camera1來(lái)操作相機.
按照慣例,源代碼AndroidVideo是第一位.
Camera2調用相機捕獲視頻的核心實(shí)現是在Camera2Capture.java中.
權限配置
要使用Android平臺提供的攝像頭,必須首先在配置文件中添加以下權限配置:
獲取相機信息
打開(kāi)相機管理器
CameraManager是用于檢測,連接和描述相機設備的系統服務(wù). 您可以通過(guò)調用Context.getSystemService(java.lang.String)方法獲取CameraManager的實(shí)例:
CameraManager mManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
獲取相機列表信息
通過(guò)調用CameraManager.getCameraIdList()方法,可以獲得攝像機ID的列表:
String[] cameraIds = mCameraManager.getCameraIdList();
for (String id : cameraIds) {
//TODO
}
可以通過(guò)相應的ID從CameraManager獲取相應攝像機的屬性集CameraCharacteristics.
在CameraCharacteristics中,您可以獲得諸如前后條件,支持的輸出尺寸,支持的輸出格式等信息.
for (String id : cameraIds) {
//傳入攝像頭id,獲取對應攝像頭的參數集
CameraCharacteristics characteristics = mManager.getCameraCharacteristics(id);
//獲取攝像頭的支持等級
Integer level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
//如果是LEGACY等級,不建議使用該攝像頭
if (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
{
continue;
}
//獲取攝像頭的朝向
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
//篩選出前置攝像頭
if (facing != CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
//StreamConfigurationMap包含了該攝像頭支持的size、format等信息
StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//獲取輸出格式為YUV_420_888時(shí)兼容的size
Size[] size = map.getOutputSizes(ImageFormat.YUV_420_888);
//獲取輸出View為SurfaceView時(shí)兼容的size
//Size[] size = map.getOutputSizes(SurfaceHolder.class);
//TODO 其他的參數,例如輸出格式、輸出幀率上下限等
}
PS: 對于Camera2采集系統,每個(gè)攝像機都有一個(gè)支持級別:
PS: 通常,如果攝像機級別為L(cháng)EVEL_3和LEVEL_FULL,建議使用Camera2進(jìn)行采集,否則建議使用具有更好兼容性的Camera1進(jìn)行視頻采集.
打開(kāi)相機
通過(guò)攝像機信息,我們可以找到所需的CameraId,然后使用該ID來(lái)獲取我們的攝像機設備CameraDevice.
函數原型是public void openCamera(String cameraId,final CameraDevice.StateCallback回調,Handler handler),
cameraId是需要打開(kāi)的攝像機的ID. 為了監視攝像機的情況,您需要傳遞一個(gè)回調,這是第二個(gè)參數CameraDevice.StateCallback. 當然,如果我們不希望打開(kāi)操作占用UI線(xiàn)程時(shí)間,
我們可以使用Looper構造HandlerThread子線(xiàn)程,然后傳入Handler.
//打開(kāi)攝像頭,正常打開(kāi)會(huì )回調到CameraDeviceStateCallback的onOpened方法
mManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
//攝像頭成功連接
//camera也就是我們需要獲取的攝像頭設備
mCameraDevice = camera;
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
//攝像頭斷開(kāi)連接
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
//打開(kāi)錯誤
}
}, mHandler);
創(chuàng )建一個(gè)采集會(huì )話(huà)
成功打開(kāi)相機并獲取相應的CameraDevice之后,我們需要創(chuàng )建一個(gè)采集會(huì )話(huà)以提供程序與相機之間的通信.
函數原型是公共抽象void createCaptureSession(列表輸出,CameraCaptureSession.StateCallback回調,Handler處理程序)引發(fā)CameraAccessException.
傳入的第一個(gè)參數是需要采集的Surface. 為了監視會(huì )話(huà)的創(chuàng )建,我們需要傳遞CameraCaptureSession.StateCallback回調. 當然,第三個(gè)參數是允許在相應的Handler所在的線(xiàn)程中執行操作.
//獲取一個(gè)采集Session會(huì )話(huà),正常流程回回調到CameraCaptureSessionStateCallback的onConfigured方法
mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceView.getHolder().getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建成功
//mCameraCaptureSession也就是新創(chuàng )建的會(huì )話(huà)
mCameraCaptureSession = session;
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建失敗
}
}, mHandler);
PS: 對于某些業(yè)務(wù)需求,有必要提高捕獲幀速率(120fps及以上). 這個(gè)createConstrainedHighSpeedCaptureSession()會(huì )話(huà)可以很好地支持此功能.
發(fā)送采集請求
當您需要開(kāi)始采集時(shí),需要構造一個(gè)采集請求,然后將該請求發(fā)送到采集會(huì )話(huà).
//創(chuàng )建一個(gè)基于錄制的請求
mRequest = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
//將需要的目標Surface加入Target列表
mRequest.addTarget(surface);
//重復發(fā)送這個(gè)請求,進(jìn)行持續的采集
mCameraCaptureSession.setRepeatingRequest(mRequest.build(), NULL, mHandler);
原創(chuàng )數據回調
在獲取Camera1時(shí),通常通過(guò)設置setPreviewCallbackWithBuffer()和addCallbackBuffer()來(lái)獲取采集的原創(chuàng )數據,那么該功能如何在Camera2中實(shí)現?
我們可以使用ImageReader類(lèi):
//ImageReader是一個(gè)數據回調模塊,類(lèi)似于Camera1的setPreviewCallbackWithBuffer
mReader = ImageReader.newInstance(mConfig.mWidth, mConfig.mHeight, mConfig.mFormat, 2);
mReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
//數據處理
image.close();
}
}, mHandler);
我們需要在createCaptureSession()的第一個(gè)參數中傳遞ImageReader的Surface:
//通過(guò)ImageReader.getSurface()獲取一個(gè)Surface并將其傳給Session中
mCameraDevice.createCaptureSession(Arrays.asList(mReader.getSurface())//....);
然后將這個(gè)目標添加到CaptureRequest中:
//當然,構造請求時(shí),需要將該Surface同時(shí)加入到Request的Target列表中
mRequest.addTarget(mReader.getSurface());
參考資料
對于Camera2相關(guān)的項目,我們通??梢詤⒖家韵马椖?
googlesamples / android-Camera2Basic
google / cameraview
結論
本文簡(jiǎn)要介紹了基于Camera2 API的Android平臺的相機采集功能.
盡管Camera2是Google推薦的當前采集框架,但是由于制造商的兼容性問(wèn)題,Camera2的API功能相對不穩定;
因此,作者仍然建議開(kāi)發(fā)以Camera1作為主要集合,而Camera2作為輔助集合的體系結構. 查看全部
本文簡(jiǎn)要介紹了如何使用Camera2相關(guān)API在移動(dòng)Android系統下進(jìn)行視頻捕獲.
Camera2是Google添加到Android 5.0中的全新API,以代替Camera1來(lái)操作相機.
按照慣例,源代碼AndroidVideo是第一位.
Camera2調用相機捕獲視頻的核心實(shí)現是在Camera2Capture.java中.
權限配置
要使用Android平臺提供的攝像頭,必須首先在配置文件中添加以下權限配置:
獲取相機信息
打開(kāi)相機管理器
CameraManager是用于檢測,連接和描述相機設備的系統服務(wù). 您可以通過(guò)調用Context.getSystemService(java.lang.String)方法獲取CameraManager的實(shí)例:
CameraManager mManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
獲取相機列表信息
通過(guò)調用CameraManager.getCameraIdList()方法,可以獲得攝像機ID的列表:
String[] cameraIds = mCameraManager.getCameraIdList();
for (String id : cameraIds) {
//TODO
}
可以通過(guò)相應的ID從CameraManager獲取相應攝像機的屬性集CameraCharacteristics.
在CameraCharacteristics中,您可以獲得諸如前后條件,支持的輸出尺寸,支持的輸出格式等信息.
for (String id : cameraIds) {
//傳入攝像頭id,獲取對應攝像頭的參數集
CameraCharacteristics characteristics = mManager.getCameraCharacteristics(id);
//獲取攝像頭的支持等級
Integer level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
//如果是LEGACY等級,不建議使用該攝像頭
if (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
{
continue;
}
//獲取攝像頭的朝向
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
//篩選出前置攝像頭
if (facing != CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
//StreamConfigurationMap包含了該攝像頭支持的size、format等信息
StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//獲取輸出格式為YUV_420_888時(shí)兼容的size
Size[] size = map.getOutputSizes(ImageFormat.YUV_420_888);
//獲取輸出View為SurfaceView時(shí)兼容的size
//Size[] size = map.getOutputSizes(SurfaceHolder.class);
//TODO 其他的參數,例如輸出格式、輸出幀率上下限等
}
PS: 對于Camera2采集系統,每個(gè)攝像機都有一個(gè)支持級別:
PS: 通常,如果攝像機級別為L(cháng)EVEL_3和LEVEL_FULL,建議使用Camera2進(jìn)行采集,否則建議使用具有更好兼容性的Camera1進(jìn)行視頻采集.
打開(kāi)相機
通過(guò)攝像機信息,我們可以找到所需的CameraId,然后使用該ID來(lái)獲取我們的攝像機設備CameraDevice.
函數原型是public void openCamera(String cameraId,final CameraDevice.StateCallback回調,Handler handler),
cameraId是需要打開(kāi)的攝像機的ID. 為了監視攝像機的情況,您需要傳遞一個(gè)回調,這是第二個(gè)參數CameraDevice.StateCallback. 當然,如果我們不希望打開(kāi)操作占用UI線(xiàn)程時(shí)間,
我們可以使用Looper構造HandlerThread子線(xiàn)程,然后傳入Handler.
//打開(kāi)攝像頭,正常打開(kāi)會(huì )回調到CameraDeviceStateCallback的onOpened方法
mManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
//攝像頭成功連接
//camera也就是我們需要獲取的攝像頭設備
mCameraDevice = camera;
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
//攝像頭斷開(kāi)連接
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
//打開(kāi)錯誤
}
}, mHandler);
創(chuàng )建一個(gè)采集會(huì )話(huà)
成功打開(kāi)相機并獲取相應的CameraDevice之后,我們需要創(chuàng )建一個(gè)采集會(huì )話(huà)以提供程序與相機之間的通信.
函數原型是公共抽象void createCaptureSession(列表輸出,CameraCaptureSession.StateCallback回調,Handler處理程序)引發(fā)CameraAccessException.
傳入的第一個(gè)參數是需要采集的Surface. 為了監視會(huì )話(huà)的創(chuàng )建,我們需要傳遞CameraCaptureSession.StateCallback回調. 當然,第三個(gè)參數是允許在相應的Handler所在的線(xiàn)程中執行操作.
//獲取一個(gè)采集Session會(huì )話(huà),正常流程回回調到CameraCaptureSessionStateCallback的onConfigured方法
mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceView.getHolder().getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建成功
//mCameraCaptureSession也就是新創(chuàng )建的會(huì )話(huà)
mCameraCaptureSession = session;
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建失敗
}
}, mHandler);
PS: 對于某些業(yè)務(wù)需求,有必要提高捕獲幀速率(120fps及以上). 這個(gè)createConstrainedHighSpeedCaptureSession()會(huì )話(huà)可以很好地支持此功能.
發(fā)送采集請求
當您需要開(kāi)始采集時(shí),需要構造一個(gè)采集請求,然后將該請求發(fā)送到采集會(huì )話(huà).
//創(chuàng )建一個(gè)基于錄制的請求
mRequest = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
//將需要的目標Surface加入Target列表
mRequest.addTarget(surface);
//重復發(fā)送這個(gè)請求,進(jìn)行持續的采集
mCameraCaptureSession.setRepeatingRequest(mRequest.build(), NULL, mHandler);
原創(chuàng )數據回調
在獲取Camera1時(shí),通常通過(guò)設置setPreviewCallbackWithBuffer()和addCallbackBuffer()來(lái)獲取采集的原創(chuàng )數據,那么該功能如何在Camera2中實(shí)現?
我們可以使用ImageReader類(lèi):
//ImageReader是一個(gè)數據回調模塊,類(lèi)似于Camera1的setPreviewCallbackWithBuffer
mReader = ImageReader.newInstance(mConfig.mWidth, mConfig.mHeight, mConfig.mFormat, 2);
mReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
//數據處理
image.close();
}
}, mHandler);
我們需要在createCaptureSession()的第一個(gè)參數中傳遞ImageReader的Surface:
//通過(guò)ImageReader.getSurface()獲取一個(gè)Surface并將其傳給Session中
mCameraDevice.createCaptureSession(Arrays.asList(mReader.getSurface())//....);
然后將這個(gè)目標添加到CaptureRequest中:
//當然,構造請求時(shí),需要將該Surface同時(shí)加入到Request的Target列表中
mRequest.addTarget(mReader.getSurface());
參考資料
對于Camera2相關(guān)的項目,我們通??梢詤⒖家韵马椖?
googlesamples / android-Camera2Basic
google / cameraview
結論
本文簡(jiǎn)要介紹了基于Camera2 API的Android平臺的相機采集功能.
盡管Camera2是Google推薦的當前采集框架,但是由于制造商的兼容性問(wèn)題,Camera2的API功能相對不穩定;
因此,作者仍然建議開(kāi)發(fā)以Camera1作為主要集合,而Camera2作為輔助集合的體系結構. 查看全部
前言
本文簡(jiǎn)要介紹了如何使用Camera2相關(guān)API在移動(dòng)Android系統下進(jìn)行視頻捕獲.
Camera2是Google添加到Android 5.0中的全新API,以代替Camera1來(lái)操作相機.
按照慣例,源代碼AndroidVideo是第一位.
Camera2調用相機捕獲視頻的核心實(shí)現是在Camera2Capture.java中.
權限配置
要使用Android平臺提供的攝像頭,必須首先在配置文件中添加以下權限配置:
獲取相機信息
打開(kāi)相機管理器
CameraManager是用于檢測,連接和描述相機設備的系統服務(wù). 您可以通過(guò)調用Context.getSystemService(java.lang.String)方法獲取CameraManager的實(shí)例:
CameraManager mManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
獲取相機列表信息
通過(guò)調用CameraManager.getCameraIdList()方法,可以獲得攝像機ID的列表:
String[] cameraIds = mCameraManager.getCameraIdList();
for (String id : cameraIds) {
//TODO
}
可以通過(guò)相應的ID從CameraManager獲取相應攝像機的屬性集CameraCharacteristics.
在CameraCharacteristics中,您可以獲得諸如前后條件,支持的輸出尺寸,支持的輸出格式等信息.
for (String id : cameraIds) {
//傳入攝像頭id,獲取對應攝像頭的參數集
CameraCharacteristics characteristics = mManager.getCameraCharacteristics(id);
//獲取攝像頭的支持等級
Integer level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
//如果是LEGACY等級,不建議使用該攝像頭
if (level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY)
{
continue;
}
//獲取攝像頭的朝向
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
//篩選出前置攝像頭
if (facing != CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
//StreamConfigurationMap包含了該攝像頭支持的size、format等信息
StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
//獲取輸出格式為YUV_420_888時(shí)兼容的size
Size[] size = map.getOutputSizes(ImageFormat.YUV_420_888);
//獲取輸出View為SurfaceView時(shí)兼容的size
//Size[] size = map.getOutputSizes(SurfaceHolder.class);
//TODO 其他的參數,例如輸出格式、輸出幀率上下限等
}
PS: 對于Camera2采集系統,每個(gè)攝像機都有一個(gè)支持級別:
PS: 通常,如果攝像機級別為L(cháng)EVEL_3和LEVEL_FULL,建議使用Camera2進(jìn)行采集,否則建議使用具有更好兼容性的Camera1進(jìn)行視頻采集.
打開(kāi)相機
通過(guò)攝像機信息,我們可以找到所需的CameraId,然后使用該ID來(lái)獲取我們的攝像機設備CameraDevice.
函數原型是public void openCamera(String cameraId,final CameraDevice.StateCallback回調,Handler handler),
cameraId是需要打開(kāi)的攝像機的ID. 為了監視攝像機的情況,您需要傳遞一個(gè)回調,這是第二個(gè)參數CameraDevice.StateCallback. 當然,如果我們不希望打開(kāi)操作占用UI線(xiàn)程時(shí)間,
我們可以使用Looper構造HandlerThread子線(xiàn)程,然后傳入Handler.
//打開(kāi)攝像頭,正常打開(kāi)會(huì )回調到CameraDeviceStateCallback的onOpened方法
mManager.openCamera(mCameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
//攝像頭成功連接
//camera也就是我們需要獲取的攝像頭設備
mCameraDevice = camera;
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
//攝像頭斷開(kāi)連接
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
//打開(kāi)錯誤
}
}, mHandler);
創(chuàng )建一個(gè)采集會(huì )話(huà)
成功打開(kāi)相機并獲取相應的CameraDevice之后,我們需要創(chuàng )建一個(gè)采集會(huì )話(huà)以提供程序與相機之間的通信.
函數原型是公共抽象void createCaptureSession(列表輸出,CameraCaptureSession.StateCallback回調,Handler處理程序)引發(fā)CameraAccessException.
傳入的第一個(gè)參數是需要采集的Surface. 為了監視會(huì )話(huà)的創(chuàng )建,我們需要傳遞CameraCaptureSession.StateCallback回調. 當然,第三個(gè)參數是允許在相應的Handler所在的線(xiàn)程中執行操作.
//獲取一個(gè)采集Session會(huì )話(huà),正常流程回回調到CameraCaptureSessionStateCallback的onConfigured方法
mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceView.getHolder().getSurface()), new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建成功
//mCameraCaptureSession也就是新創(chuàng )建的會(huì )話(huà)
mCameraCaptureSession = session;
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
//會(huì )話(huà)創(chuàng )建失敗
}
}, mHandler);
PS: 對于某些業(yè)務(wù)需求,有必要提高捕獲幀速率(120fps及以上). 這個(gè)createConstrainedHighSpeedCaptureSession()會(huì )話(huà)可以很好地支持此功能.
發(fā)送采集請求
當您需要開(kāi)始采集時(shí),需要構造一個(gè)采集請求,然后將該請求發(fā)送到采集會(huì )話(huà).
//創(chuàng )建一個(gè)基于錄制的請求
mRequest = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
//將需要的目標Surface加入Target列表
mRequest.addTarget(surface);
//重復發(fā)送這個(gè)請求,進(jìn)行持續的采集
mCameraCaptureSession.setRepeatingRequest(mRequest.build(), NULL, mHandler);
原創(chuàng )數據回調
在獲取Camera1時(shí),通常通過(guò)設置setPreviewCallbackWithBuffer()和addCallbackBuffer()來(lái)獲取采集的原創(chuàng )數據,那么該功能如何在Camera2中實(shí)現?
我們可以使用ImageReader類(lèi):
//ImageReader是一個(gè)數據回調模塊,類(lèi)似于Camera1的setPreviewCallbackWithBuffer
mReader = ImageReader.newInstance(mConfig.mWidth, mConfig.mHeight, mConfig.mFormat, 2);
mReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireNextImage();
//數據處理
image.close();
}
}, mHandler);
我們需要在createCaptureSession()的第一個(gè)參數中傳遞ImageReader的Surface:
//通過(guò)ImageReader.getSurface()獲取一個(gè)Surface并將其傳給Session中
mCameraDevice.createCaptureSession(Arrays.asList(mReader.getSurface())//....);
然后將這個(gè)目標添加到CaptureRequest中:
//當然,構造請求時(shí),需要將該Surface同時(shí)加入到Request的Target列表中
mRequest.addTarget(mReader.getSurface());
參考資料
對于Camera2相關(guān)的項目,我們通??梢詤⒖家韵马椖?
googlesamples / android-Camera2Basic
google / cameraview
結論
本文簡(jiǎn)要介紹了基于Camera2 API的Android平臺的相機采集功能.
盡管Camera2是Google推薦的當前采集框架,但是由于制造商的兼容性問(wèn)題,Camera2的API功能相對不穩定;
因此,作者仍然建議開(kāi)發(fā)以Camera1作為主要集合,而Camera2作為輔助集合的體系結構.
PHP+fiddler抓包采集微信文章閱讀數點(diǎn)贊數的思路解讀
采集交流 ? 優(yōu)采云 發(fā)表了文章 ? 0 個(gè)評論 ? 378 次瀏覽 ? 2020-08-04 09:00
更新時(shí)間:2019年12月20日 10:02:43 轉載作者:flysnownet
這篇文章主要介紹了PHP+fiddler抓包采集微信文章閱讀數點(diǎn)贊數的思路,非常不錯,具有一定的參考借鑒價(jià)值,需要的同學(xué)可以參考下
簡(jiǎn)介:
分析插口曉得要獲取文章閱讀數和點(diǎn)贊數必須有key和uin這兩個(gè)關(guān)鍵參數文章采集api,不同公眾號key不一樣(據說(shuō)有萬(wàn)能陌陌key,不懂如何搞到)文章采集api,同一個(gè)公眾號key大約半小時(shí)會(huì )過(guò)期
提交鏈接獲取文章閱讀量api
思路:
1.將客戶(hù)端懇求閱讀量插口的懇求攔截轉發(fā)到自己服務(wù)器,這樣就可以獲取到key ,用__biz關(guān)聯(lián)緩存半小時(shí)
2.提交文章鏈接進(jìn)行查詢(xún)時(shí),服務(wù)器從文章鏈接里獲取__biz,查詢(xún)是否緩存了當前公眾號對應的key,有的話(huà)進(jìn)行第3步,沒(méi)有進(jìn)行第4步。
3.curl懇求 接口獲取數據
4.key不存在時(shí),通知客戶(hù)端重定向到該url(通知用websocket通知或則客戶(hù)端ajax協(xié)程,需要用抓包工具更改文章詳情頁(yè)代碼使其跳轉到中間頁(yè)面待命,打開(kāi)文章頁(yè)面后隔幾秒挪到中間頁(yè))并暫停程序幾秒等待客戶(hù)端更新key,此時(shí)客戶(hù)端遞交了新的key,用其進(jìn)行查詢(xún)
實(shí)現
1.抓包
此插口就是獲取閱讀量的插口,參數如下圖
2.將此插口攔截轉發(fā)到自己服務(wù)器,點(diǎn)擊 rules- customize rules 在OnBeforeRequest(正式懇求之前執行的函數)加上
if (oSession.fullUrl.Contains("mp.weixin.qq.com/mp/getappmsgext"))
{
oSession.oRequest["Host"]= 'ccc.aaa.com' ;
}
效果,可以見(jiàn)到此插口早已被轉發(fā)
3.服務(wù)端緩存key,代碼以PHP為例
public function saveKey(Request $request)
{
$__biz = $request->param('__biz',0);
$data['uin'] = $request->param('uin',0);
$data['key'] = $request->param('key',0);
Cache::set($__biz,$data,30 * 60);
return 'ok';
}
4.提交文章鏈接查詢(xún)API代碼
public function getReadNum(Request $request)
{
$url = $request->param('url');
parse_str(parse_url($url)['query'], $param);
$__biz = $param['__biz'];
$key_data = Cache::get($__biz);
if (empty($key_data))
return 'no key';
$uin = $key_data['uin'];
$key = $key_data['key'];
$param['uin'] = $uin;
$param['key'] = $key;
$param['wxtoken'] = "777";
$wechat_url = "https://mp.weixin.qq.com/mp/getappmsgext?" . http_build_query($param);
//dump($wechat_url);
$data = array(
'is_only_read' => 1,
'is_temp_url' => 0,
'appmsg_type' => 9,
);
$res = $this->get_url($wechat_url,$data);
return $res;
}
function get_url($url,$data)
{
$ifpost = 1;//是否post請求
$datafields = $data;//post數據
$cookiefile = '';//cookie文件
$cookie = '';//cookie變量
$v = false;
//模擬http請求header頭
$header = array("Connection: Keep-Alive","Accept: text/html, application/xhtml+xml, */*", "Pragma: no-cache", "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3","User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1278.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.5 WindowsWechat");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, $v);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$ifpost && curl_setopt($ch, CURLOPT_POST, $ifpost);
$ifpost && curl_setopt($ch, CURLOPT_POSTFIELDS, $datafields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$cookie && curl_setopt($ch, CURLOPT_COOKIE, $cookie);//發(fā)送cookie變量
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);//發(fā)送cookie文件
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile);//寫(xiě)入cookie到文件
curl_setopt($ch,CURLOPT_TIMEOUT,60); //允許執行的最長(cháng)秒數
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$ok = curl_exec($ch);
curl_close($ch);
unset($ch);
return $ok;
}
5.通知客戶(hù)端重定向頁(yè)面(這部份沒(méi)寫(xiě),看參考我的其他關(guān)于文本socket文章)
6.用fiddler更改陌陌文章也jsj腳本,
在OnBeforeResponse(返回給客戶(hù)端之前執行的方式),加上跳轉到中間頁(yè)的代碼
效果
總結 查看全部
這篇文章主要介紹了PHP+fiddler抓包采集微信文章閱讀數點(diǎn)贊數的思路,非常不錯,具有一定的參考借鑒價(jià)值,需要的同學(xué)可以參考下
簡(jiǎn)介:
分析插口曉得要獲取文章閱讀數和點(diǎn)贊數必須有key和uin這兩個(gè)關(guān)鍵參數文章采集api,不同公眾號key不一樣(據說(shuō)有萬(wàn)能陌陌key,不懂如何搞到)文章采集api,同一個(gè)公眾號key大約半小時(shí)會(huì )過(guò)期
提交鏈接獲取文章閱讀量api
思路:
1.將客戶(hù)端懇求閱讀量插口的懇求攔截轉發(fā)到自己服務(wù)器,這樣就可以獲取到key ,用__biz關(guān)聯(lián)緩存半小時(shí)
2.提交文章鏈接進(jìn)行查詢(xún)時(shí),服務(wù)器從文章鏈接里獲取__biz,查詢(xún)是否緩存了當前公眾號對應的key,有的話(huà)進(jìn)行第3步,沒(méi)有進(jìn)行第4步。
3.curl懇求 接口獲取數據
4.key不存在時(shí),通知客戶(hù)端重定向到該url(通知用websocket通知或則客戶(hù)端ajax協(xié)程,需要用抓包工具更改文章詳情頁(yè)代碼使其跳轉到中間頁(yè)面待命,打開(kāi)文章頁(yè)面后隔幾秒挪到中間頁(yè))并暫停程序幾秒等待客戶(hù)端更新key,此時(shí)客戶(hù)端遞交了新的key,用其進(jìn)行查詢(xún)
實(shí)現
1.抓包
此插口就是獲取閱讀量的插口,參數如下圖
2.將此插口攔截轉發(fā)到自己服務(wù)器,點(diǎn)擊 rules- customize rules 在OnBeforeRequest(正式懇求之前執行的函數)加上
if (oSession.fullUrl.Contains("mp.weixin.qq.com/mp/getappmsgext"))
{
oSession.oRequest["Host"]= 'ccc.aaa.com' ;
}
效果,可以見(jiàn)到此插口早已被轉發(fā)
3.服務(wù)端緩存key,代碼以PHP為例
public function saveKey(Request $request)
{
$__biz = $request->param('__biz',0);
$data['uin'] = $request->param('uin',0);
$data['key'] = $request->param('key',0);
Cache::set($__biz,$data,30 * 60);
return 'ok';
}
4.提交文章鏈接查詢(xún)API代碼
public function getReadNum(Request $request)
{
$url = $request->param('url');
parse_str(parse_url($url)['query'], $param);
$__biz = $param['__biz'];
$key_data = Cache::get($__biz);
if (empty($key_data))
return 'no key';
$uin = $key_data['uin'];
$key = $key_data['key'];
$param['uin'] = $uin;
$param['key'] = $key;
$param['wxtoken'] = "777";
$wechat_url = "https://mp.weixin.qq.com/mp/getappmsgext?" . http_build_query($param);
//dump($wechat_url);
$data = array(
'is_only_read' => 1,
'is_temp_url' => 0,
'appmsg_type' => 9,
);
$res = $this->get_url($wechat_url,$data);
return $res;
}
function get_url($url,$data)
{
$ifpost = 1;//是否post請求
$datafields = $data;//post數據
$cookiefile = '';//cookie文件
$cookie = '';//cookie變量
$v = false;
//模擬http請求header頭
$header = array("Connection: Keep-Alive","Accept: text/html, application/xhtml+xml, */*", "Pragma: no-cache", "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3","User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1278.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.5 WindowsWechat");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, $v);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$ifpost && curl_setopt($ch, CURLOPT_POST, $ifpost);
$ifpost && curl_setopt($ch, CURLOPT_POSTFIELDS, $datafields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$cookie && curl_setopt($ch, CURLOPT_COOKIE, $cookie);//發(fā)送cookie變量
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);//發(fā)送cookie文件
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile);//寫(xiě)入cookie到文件
curl_setopt($ch,CURLOPT_TIMEOUT,60); //允許執行的最長(cháng)秒數
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$ok = curl_exec($ch);
curl_close($ch);
unset($ch);
return $ok;
}
5.通知客戶(hù)端重定向頁(yè)面(這部份沒(méi)寫(xiě),看參考我的其他關(guān)于文本socket文章)
6.用fiddler更改陌陌文章也jsj腳本,
在OnBeforeResponse(返回給客戶(hù)端之前執行的方式),加上跳轉到中間頁(yè)的代碼
效果
總結 查看全部
更新時(shí)間:2019年12月20日 10:02:43 轉載作者:flysnownet
這篇文章主要介紹了PHP+fiddler抓包采集微信文章閱讀數點(diǎn)贊數的思路,非常不錯,具有一定的參考借鑒價(jià)值,需要的同學(xué)可以參考下
簡(jiǎn)介:
分析插口曉得要獲取文章閱讀數和點(diǎn)贊數必須有key和uin這兩個(gè)關(guān)鍵參數文章采集api,不同公眾號key不一樣(據說(shuō)有萬(wàn)能陌陌key,不懂如何搞到)文章采集api,同一個(gè)公眾號key大約半小時(shí)會(huì )過(guò)期
提交鏈接獲取文章閱讀量api
思路:
1.將客戶(hù)端懇求閱讀量插口的懇求攔截轉發(fā)到自己服務(wù)器,這樣就可以獲取到key ,用__biz關(guān)聯(lián)緩存半小時(shí)
2.提交文章鏈接進(jìn)行查詢(xún)時(shí),服務(wù)器從文章鏈接里獲取__biz,查詢(xún)是否緩存了當前公眾號對應的key,有的話(huà)進(jìn)行第3步,沒(méi)有進(jìn)行第4步。
3.curl懇求 接口獲取數據
4.key不存在時(shí),通知客戶(hù)端重定向到該url(通知用websocket通知或則客戶(hù)端ajax協(xié)程,需要用抓包工具更改文章詳情頁(yè)代碼使其跳轉到中間頁(yè)面待命,打開(kāi)文章頁(yè)面后隔幾秒挪到中間頁(yè))并暫停程序幾秒等待客戶(hù)端更新key,此時(shí)客戶(hù)端遞交了新的key,用其進(jìn)行查詢(xún)
實(shí)現
1.抓包
此插口就是獲取閱讀量的插口,參數如下圖


2.將此插口攔截轉發(fā)到自己服務(wù)器,點(diǎn)擊 rules- customize rules 在OnBeforeRequest(正式懇求之前執行的函數)加上
if (oSession.fullUrl.Contains("mp.weixin.qq.com/mp/getappmsgext"))
{
oSession.oRequest["Host"]= 'ccc.aaa.com' ;
}

效果,可以見(jiàn)到此插口早已被轉發(fā)

3.服務(wù)端緩存key,代碼以PHP為例
public function saveKey(Request $request)
{
$__biz = $request->param('__biz',0);
$data['uin'] = $request->param('uin',0);
$data['key'] = $request->param('key',0);
Cache::set($__biz,$data,30 * 60);
return 'ok';
}
4.提交文章鏈接查詢(xún)API代碼
public function getReadNum(Request $request)
{
$url = $request->param('url');
parse_str(parse_url($url)['query'], $param);
$__biz = $param['__biz'];
$key_data = Cache::get($__biz);
if (empty($key_data))
return 'no key';
$uin = $key_data['uin'];
$key = $key_data['key'];
$param['uin'] = $uin;
$param['key'] = $key;
$param['wxtoken'] = "777";
$wechat_url = "https://mp.weixin.qq.com/mp/getappmsgext?" . http_build_query($param);
//dump($wechat_url);
$data = array(
'is_only_read' => 1,
'is_temp_url' => 0,
'appmsg_type' => 9,
);
$res = $this->get_url($wechat_url,$data);
return $res;
}
function get_url($url,$data)
{
$ifpost = 1;//是否post請求
$datafields = $data;//post數據
$cookiefile = '';//cookie文件
$cookie = '';//cookie變量
$v = false;
//模擬http請求header頭
$header = array("Connection: Keep-Alive","Accept: text/html, application/xhtml+xml, */*", "Pragma: no-cache", "Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3","User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36 QBCore/4.0.1278.400 QQBrowser/9.0.2524.400 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2875.116 Safari/537.36 NetType/WIFI MicroMessenger/7.0.5 WindowsWechat");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, $v);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$ifpost && curl_setopt($ch, CURLOPT_POST, $ifpost);
$ifpost && curl_setopt($ch, CURLOPT_POSTFIELDS, $datafields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$cookie && curl_setopt($ch, CURLOPT_COOKIE, $cookie);//發(fā)送cookie變量
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile);//發(fā)送cookie文件
$cookiefile && curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile);//寫(xiě)入cookie到文件
curl_setopt($ch,CURLOPT_TIMEOUT,60); //允許執行的最長(cháng)秒數
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$ok = curl_exec($ch);
curl_close($ch);
unset($ch);
return $ok;
}
5.通知客戶(hù)端重定向頁(yè)面(這部份沒(méi)寫(xiě),看參考我的其他關(guān)于文本socket文章)
6.用fiddler更改陌陌文章也jsj腳本,
在OnBeforeResponse(返回給客戶(hù)端之前執行的方式),加上跳轉到中間頁(yè)的代碼
效果

總結


