2Captcha + python + selenium ERROR_ZERO_CAPTCHA_FILESIZE - python

I'm trying to upload an image captcha to 2captcha API but I'm receiving the error ERROR_ZERO_CAPTCHA_FILESIZE but my file size on my directory is above 60KB why am I still receiving this error?
Am I missing something?
I've tried sending the only captcha image(originally downloaded from the source) but I received the same error or TOO_MANY_BAD_IMAGES. Please help me.
CODE:
from selenium import webdriver
import requests
driverop = webdriver.ChromeOptions()
driverop.add_argument("--start-maximized")
proxy = "118.174.233.45:44061"
driverop = webdriver.ChromeOptions()
driverop.add_argument('--proxy-server=%s' % proxy)
driver = webdriver.Chrome("chromedriver/chromedriver",options=driverop)
driver.get("https://accounts.google.com/o/oauth2/auth/oauthchooseaccount?client_id=717762328687-iludtf96g1hinl76e4lc1b9a82g457nn.apps.googleusercontent.com&scope=profile%20email&redirect_uri=https%3A%2F%2Fstackauth.com%2Fauth%2Foauth2%2Fgoogle&state=%7B%22sid%22%3A1%2C%22st%22%3A%2259%3A3%3Abbc%2C16%3Af9ef16faad8743e2%2C10%3A1609613474%2C16%3Aa2c13dc2511eb0d0%2Ccb47135ca2a3bc9ca4ee712429ddf5c0935588f518c964242057bb74b818d4de%22%2C%22cdl%22%3Anull%2C%22cid%22%3A%22717762328687-iludtf96g1hinl76e4lc1b9a82g457nn.apps.googleusercontent.com%22%2C%22k%22%3A%22Google%22%2C%22ses%22%3A%22e15efb6754f4498991cd1d37a967f325%22%7D&response_type=code&flowName=GeneralOAuthFlow")
driver.find_element_by_id("identifierId").send_keys(EMAIL)
driver.find_element_by_css_selector('.VfPpkd-LgbsSe-OWXEXe-k8QpJ > div:nth-child(3)').click()
driver.save_screenshot("sample.png")
url = 'http://2captcha.com/in.php'
API_KEY = "---"
files = {'file': open('sample.png',"rb")}
data = {'key': API_KEY, 'method': 'post'}
r = requests.post(url, files=files, data=data)
if r.ok:
print(r)
url = "http://2captcha.com/in.php?key="+API_KEY+"&action=get&id="+r.text[3:]
for xr in range(1, 10):
sleep(1.5) # wait 5 sec.
resp = requests.get(url)
if resp.text[0:2] == 'OK':
break
else:
print(resp)

If you use the driver.save_screenshot you will save the current window, according the documentation (WebDriver.save_screenshot). Try to return the element and use the webelement.screenshot method (WebElement.screenshot)
from selenium import webdriver
import requests
driverop = webdriver.ChromeOptions()
driverop.add_argument("--start-maximized")
proxy = "118.174.233.45:44061"
driverop = webdriver.ChromeOptions()
driverop.add_argument('--proxy-server=%s' % proxy)
driver = webdriver.Chrome("chromedriver/chromedriver",options=driverop)
driver.get("https://accounts.google.com/o/oauth2/auth/oauthchooseaccount?client_id=717762328687-iludtf96g1hinl76e4lc1b9a82g457nn.apps.googleusercontent.com&scope=profile%20email&redirect_uri=https%3A%2F%2Fstackauth.com%2Fauth%2Foauth2%2Fgoogle&state=%7B%22sid%22%3A1%2C%22st%22%3A%2259%3A3%3Abbc%2C16%3Af9ef16faad8743e2%2C10%3A1609613474%2C16%3Aa2c13dc2511eb0d0%2Ccb47135ca2a3bc9ca4ee712429ddf5c0935588f518c964242057bb74b818d4de%22%2C%22cdl%22%3Anull%2C%22cid%22%3A%22717762328687-iludtf96g1hinl76e4lc1b9a82g457nn.apps.googleusercontent.com%22%2C%22k%22%3A%22Google%22%2C%22ses%22%3A%22e15efb6754f4498991cd1d37a967f325%22%7D&response_type=code&flowName=GeneralOAuthFlow")
driver.find_element_by_id("identifierId").send_keys(EMAIL)
element = driver.find_element_by_css_selector('.VfPpkd-LgbsSe-OWXEXe-k8QpJ > div:nth-child(3)').click()
element.screenshot("sample.png")
url = 'http://2captcha.com/in.php'
API_KEY = "---"
files = {'file': open('sample.png',"rb")}
data = {'key': API_KEY, 'method': 'post'}
r = requests.post(url, files=files, data=data)
if r.ok:
print(r)
url = "http://2captcha.com/in.php?key="+API_KEY+"&action=get&id="+r.text[3:]
for xr in range(1, 10):
sleep(1.5) # wait 5 sec.
resp = requests.get(url)
if resp.text[0:2] == 'OK':
break
else:
print(resp)

Regarding your comment, I think your problem is using 2captcha API?
If so, instead of using request module, try their in-house API TwoCaptcha.
Install it by: pip3 install 2captcha-python
I have a snippet here that you can try to upload your sample:
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
from twocaptcha import TwoCaptcha
api_key = os.getenv('APIKEY_2CAPTCHA', 'YOUR_API_KEY')
solver = TwoCaptcha(api_key)
try:
result = solver.normal('path/to/captcha.jpg')
except Exception as e:
sys.exit(e)
else:
sys.exit('solved: ' + str(result))

No need to use selenium and more lines of code to solve captcha. Just use the below short code, it will resolve and provide the response token.
Note: It will handle, image selection as well (car, bus, ship, truck and so on)
-- sitekey - inspect element and find data-sitekey attribute, you will get it
-- url - your webite url
import requests
from twocaptcha import TwoCaptcha
twoCaptcha =TwoCaptcha('xxxxxxxxxxxxxxx') # Your 2captcha API key
captcha_token = twoCaptcha.recaptcha(sitekey='xxxxxxxxxxxxxx',
url='website url')
print(captcha_token)

Related

I want to get orderID from API response using selenium python

I want to get the order ID from the API response. When I click on the Create Order button it will send a POST API request and return the unique ID that I want.
This is my order creation code.
from datetime import date
import time
from seleniumwire import webdriver
from openpyxl import load_workbook
from Locators.PracticeLocators import PracticeLocators
from pageObjects.LoginPage import LoginScreen
today = date.today()
currentDate = today.strftime("%m/%d/%Y")
FilePath = "C:/Users/Administrator/PycharmProject/LegrandePython/TestData/Data.xlsx"
datafile = load_workbook(FilePath)
testData = datafile['Test Data']
loginData = datafile["Login Credentials"]
scriptData = datafile["Script Data"]
driver = webdriver.Chrome(executable_path="C:/Users/Administrator/Downloads/chromedriver.exe")
driver.maximize_window()
driver.scopes = [
'.*https://ibis-dev.droicelabs.us/api/dispenser/orders/.*'
]
driver.get(loginData.cell(4, 2).value)
driver.implicitly_wait(5)
login = LoginScreen(driver)
login.SetUsername(loginData.cell(4, 3).value)
login.SetPassword(loginData.cell(4, 4).value)
login.SignIn()
driver.implicitly_wait(20)
driver.find_element_by_class_name(PracticeLocators.Add_RX).click()
PatientSearch = driver.find_element_by_xpath(PracticeLocators.Patient_search_textbox)
PatientSearch.click()
PatientSearch.send_keys(testData.cell(2, 1).value)
driver.find_element_by_xpath("(//*[text()='" + testData.cell(2, 2).value + "'])[1]").click()
DoctorSearch = driver.find_element_by_xpath(PracticeLocators.doctor_search_textbox)
DoctorSearch.click()
time.sleep(1)
DoctorSearch.send_keys(scriptData.cell(2, 8).value)
time.sleep(1)
driver.find_element_by_xpath(
"(//*[text()='" + scriptData.cell(2, 8).value + " " + "Practice'])[2]").click()
driver.find_element_by_xpath(PracticeLocators.NextButton).click()
driver.find_element_by_xpath(PracticeLocators.CreateOnetimeRXButton).click()
driver.find_element_by_name(PracticeLocators.OnetimeSearchMedicine).send_keys(scriptData.cell(2, 1).value)
time.sleep(2)
driver.find_element_by_xpath("//*[text()='" + scriptData.cell(2, 1).value + "']").click()
driver.find_element_by_xpath(PracticeLocators.AddButton).click()
driver.find_element_by_xpath(PracticeLocators.ProductQuantity).click()
time.sleep(1)
driver.find_element_by_xpath(PracticeLocators.Quantity).click()
driver.find_element_by_xpath(PracticeLocators.ProductRefilles).click()
time.sleep(1)
driver.find_element_by_xpath(PracticeLocators.Quantity).click()
time.sleep(2)
driver.find_element_by_xpath(PracticeLocators.DAWCheckbox).click()
time.sleep(2)
instruction = driver.find_element_by_xpath(PracticeLocators.productInstruction)
instruction.click()
instruction.send_keys(testData.cell(2, 3).value)
driver.find_element_by_xpath(PracticeLocators.allergiesButton).click()
allergies = driver.find_element_by_xpath(PracticeLocators.allergiesTextbox)
allergies.clear()
allergies.send_keys(testData.cell(2, 4).value)
driver.find_element_by_xpath(PracticeLocators.doneButton).click()
driver.find_element_by_xpath(PracticeLocators.addDropchartButton).click()
time.sleep(2)
element = driver.find_element_by_xpath(PracticeLocators.selectDocuments)
driver.execute_script("arguments[0].click()", element)
driver.find_element_by_xpath(PracticeLocators.selectButton).click()
driver.find_element_by_xpath(PracticeLocators.skipPayment).click()
driver.find_element_by_xpath(PracticeLocators.surgeryDate).send_keys(currentDate)
createOrderButton = driver.find_element_by_xpath(PracticeLocators.submit_CreateOrderButton)
driver.execute_script("arguments[0].click()", createOrderButton)
for request in driver.requests:
if request.response:
print(
request.url,
request.response.status_code,
request.response.headers['Content-Type'])
time.sleep(7)
When self.driver.execute_script("arguments[0].click()", createOrderButton) this line execute it will send the POST API https://ibis-dev.droicelabs.us/api/dispenser/orders/ and return unique order id that I want.
I have give scope but it will return many API call
driver.scopes = [
'.*https://ibis-dev.droicelabs.us/api/dispenser/orders/.*'
]
https://ibis-dev.droicelabs.us/api/dispenser/orders/ this API will call when I click on the create order button and return order id.
It will not show the API that I have used in a scope. And how to get the response of that API which I have given in scope.
I am new to selenium python and I have done it in cypress. but don't know how to do it using selenium python.
This is how to capture HTTP requests using Selenium:
1 Install package
pip install selenium-wire
2 Use driver.requests to get some data
from seleniumwire import webdriver
driver = webdriver.Chrome()
# do you actions with driver
for request in driver.requests:
if request.response:
print(
request.url,
request.response.status_code,
request.response.headers['Content-Type'])
3 You might want to limit requests capture to some specific hosts
https://pypi.org/project/selenium-wire/#limiting-request-capture
driver.scopes = [
'.*ibis-dev.droicelabs.us/api/dispenser/orders/.*'
]
4 How to read response body
import json
...
for request in driver.requests:
if request.response:
data = json.loads(request.response.body)
print(data['foo'])
Answering this question - get order id
The final solution for getting order_id for multiple portals which handles UnicodeDecodeError, JSONDecodeError errors and prints some debug details:
#define scopes to capture the required requests
driver.scopes = [
'.*/api/dispenser/orders/.*',
'.*/api/practice/orders/.*',
'.*/api/practice/subscriptions/.*'
]
# UI steps performed...
# The last UI action
createOrderButton = driver.find_element_by_xpath(PracticeLocators.submit_CreateOrderButton)
driver.execute_script("arguments[0].click()", createOrderButton)
time.sleep(5)
order_id = None
# read requests for order_id
for request in driver.requests:
if request.response:
if request.method == 'POST':
print(request.method + ' ' + request.url)
try:
data = json.loads(request.response.body)
print('parsed as json')
if '_id' in data:
order_id = data['_id']
except UnicodeDecodeError:
try:
data = json.loads(decompress(request.response.body))
print('decompressed and parsed as json')
if '_id' in data:
order_id = data['_id']
except json.decoder.JSONDecodeError:
data = request.response.body
print('decompressed and parsed as string')
print(data)
print(order_id)
Limitations
Selenium Wire will currently work with tests that run on the same machine as the browser. A distributed setup using Selenium Grid is not yet supported.
Sites that use NTLM authentication (Windows authentication) cannot currently be tested with Selenium Wire. NTLM authentication is not supported.
Reference
https://pypi.org/project/selenium-wire/

Deploy a simple Python bot

Code:
import requests as rq
from bs4 import BeautifulSoup as bs
url = "https://apod.nasa.gov/apod/astropix.html"
page = rq.get(url).content
soup = bs(page, 'html.parser')
response = soup.find('img')
if response == None:
imglink = soup.find('iframe')['src']
else:
imglink = 'https://apod.nasa.gov/apod/' + response['src']
def main():
sess = rq.Session()
cid='**************'
turl = 'https://api.telegram.org/bot*******************/'
if response == None:
imglink = soup.find('iframe')['src']
params = {'chat_id':cid,'text':imglink}
sess.post(turl + 'sendMessage', data=params)
else:
imglink = 'https://apod.nasa.gov/apod/' + response['src']
title = soup.find('b').get_text()
params = {'chat_id':cid,'photo':imglink,'caption':title}
sess.post(turl + 'sendPhoto', data=params)
if __name__ == '__main__':
main()
This is a simple bot for sending Nasa picture to my telegram channel. I will be modifying this script to make it happen everyday. But he Question is where do I host them, So that it will run all the time (free) . What is the correct way of doing it.
I don't know of any providers that would host this for free. For cheap, AWS and Google Cloud all have simple solutions.
Ex: https://cloud.google.com/blog/products/application-development/how-to-schedule-a-recurring-python-script-on-gcp

Google URL Shortener API always returns same page with pagetoken

I am attempting to use the Google UrlShortener API to retrieve history with OAuth2 and an API key. I am getting a 200 OK response but when I try and get subsequent pages using pagetoken or pageToken as a query parameter I always get the same nextPageToken and the same page of results. Oddly, the browser based Google API interaction uses start-token not pagetoken or pageToken but when I use start-token I don't get a 200 OK.
How do I get pagination to work with the UrlShortener API?
Here is my code:
import requests
import json
import time
import settings
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run_flow
from oauth2client.file import Storage
def history():
"""Look up a user's history"""
flow = OAuth2WebServerFlow(client_id=settings.OAUTH2_CLIENT_ID,
client_secret=settings.CLIENT_SECRET,
scope='https://www.googleapis.com/auth/urlshortener',
redirect_uri='http://127.0.0.1:5000/callback')
storage = Storage('creds.data')
credentials = run_flow(flow, storage)
print("access_token: {}".format(credentials.access_token))
headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer {}'.format(credentials.access_token)}
raw_url = 'https://www.googleapis.com/urlshortener/v1/url/history'
url = raw_url + '?key={}'.format(settings.API_KEY)
r = requests.get(url=url, headers=headers)
if r.ok:
output = "The history is {}.".format(r.json())
print(output)
if 'nextPageToken' in r.json().keys():
morePages = True
npt = r.json()['nextPageToken']
r_paged = None
while morePages:
time.sleep(2)
url = raw_url + '?pagetoken={}&key={}'.format(npt, settings.API_KEY)
r_paged = requests.get(url=url, headers=headers)
if r_paged.ok:
if 'nextPageToken' in r_paged.json().keys():
npt = r_paged.json()['nextPageToken']
morePages = True
else:
morePages = False
break
output = "The history is {}.".format(r_paged.json())
print(output)
else:
output = "Invalid request. Status code = {}, json = {}".format(r_paged.status_code, r_paged.json())
print(output)
else:
output = "Invalid request. Status code = {}, json = {}".format(r.status_code, r.json())
print(output)
Fixed code follows:
# New import:
import urllib.parse
# // snip
time.sleep(2)
f = {'start-token':npt, 'key': settings.API_KEY}
formatted = '?' + urllib.parse.urlencode(f)
url = raw_url + formatted
r_paged = requests.get(url=url, headers=headers)
# // snip
Basically, ignore the documentation. Do NOT use pageToken, use start-token. Furthermore, you need to use the url parser suitable for Python 3 for urlencoding.

Equivalent Python code for the following Java http get requests

I am trying to convert the following Java code to Python. Not sure what I am doing wrong, but I end up with an internal server error 500 with python.
Is the "body" in httplib.httpConnection method equivalent to Java httpentity?
Any other thoughts on what could be wrong?
The input information I collect is correct for sure.
Any help will be really appreciated. I have tried several things, but end up with the same internal server error.
Java Code:
HttpEntity reqEntitiy = new StringEntity("loginTicket="+ticket);
HttpRequestBase request = reMethod.getRequest(uri, reqEntitiy);
request.addHeader("ticket", ticket);
HttpResponse response = httpclient.execute(request);
HttpEntity responseEntity = response.getEntity();
StatusLine responseStatus = response.getStatusLine();
Python code:
url = serverURL + "resources/slmservices/templates/"+templateId+"/options"
#Create the request
ticket = ticket.replace("'",'"')
headers = {"ticket":ticket}
print "ticket",ticket
reqEntity = "loginTicket="+ticket
body = "loginTicket="+ticket
url2 = urlparse.urlparse(serverURL)
h1 = httplib.HTTPConnection(url2.hostname,8580)
print "h1",h1
url3 = urlparse.urlparse(url)
print "url path",url3.path
ubody = {"loginTicket":ticket}
data = urllib.urlencode(ubody)
conn = h1.request("GET",url3.path,data,headers)
#conn = h1.request("GET",url3.path)
response = h1.getresponse()
lines = response.read()
print "response.status",response.status
print "response.reason",response.reason
You don't need to go this low level. Using urllib2 instead:
import urllib2
from urllib import urlencode
url = "{}resources/slmservices/templates/{}/options".format(
serverURL, templateId)
headers = {"ticket": ticket}
params = {"loginTicket": ticket}
url = '{}?{}'.format(url, urlencode(params))
request = urllib2.Request(url, headers=headers)
response = urllib2.urlopen(request)
print 'Status', response.getcode()
print 'Response data', response.read()
Note that the parameters are added to the URL to form URL query parameters.
You can do this simpler still by installing the requests library:
import requests
url = "{}resources/slmservices/templates/{}/options".format(
serverURL, templateId)
headers = {"ticket": ticket}
params = {"loginTicket": ticket}
response = requests.get(url, params=params, headers=headers)
print 'Status', response.status
print 'Response data', response.content # or response.text for Unicode
Here requests takes care of URL-encoding the URL query string parameters and adding it to the URL for you, just like Java does.

Send cookies with urllib2 python

Note: Driver is logged into the website "https://www.example.com"
import urllib,cookielib
jar = cookielib.FileCookieJar("cookies")
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar))
data_str = ''
all_cookies = driver.get_cookies()
for cookie_name, cookie_value in all_cookies[0].items():
data_str = data_str+cookie_name+'='+str(cookie_value)+';'
opener.addheaders.append( ('Cookie', data_str) )
url = "https://www.example.com/path/"
f = opener.open(url)
print f.read()
This gives me the login page instead of the actual page from url. Can anyone help ?

Categories