Create new dialog in PyQT + Webview - qt

I`m trying to develop nice-looking app in pyqt using WebView and have a little problem.
I want to create new Window by pressing button in WebView.
I have main window(short view):
class LoginWindow(QWidget):
def __init__(self):
# creating window and different properties...
# Its not important,i think.
self.foo = LoginConnector(self)
view.page().mainFrame().addToJavaScriptWindowObject("foo", self.foo)
... connector to JS
class LoginConnector(QObject):
#pyqtSlot(result=str)
def get_user_list(self):
return ','.join(core.available_users())
#pyqtSlot()
def new_window(self):
print 'Hello!'
#What can i do here?
#pyqtSlot()
def quit(self):
QApplication.quit()
When i`m pressing button in window,its call new_window() from LoginConnector,but how create Dialog inside LoginConnector?
Full code
SOLVED! I`m idiot,listen that clever guy below

Just look at the api docs. http://pyqt.sourceforge.net/Docs/PyQt4/classes.html
If you don't like this PySide is basically the same thing with a few differences in syntax. http://pyside.github.io/docs/pyside/
class LoginWindow(QWebView):
def __init__(self, *args, **kwargs):
super(QWebView, self).__init__(*args, **kwargs):
...
self.foo = LoginConnector(self)
self.loadPage("httpdocs/login.hmtl")
# end Constructor
def loadPage(self, web_page):
"""Loads a web page in the browser.
Args:
webPage (str): The URL of the desired web page with JavaScript Python Communication.
"""
# Inspector - right click inspect to debug javascript and have access to the console.
inspector = QtWebKit.QWebInspector()
inspector.setPage(self.page())
# Force relative path otherwise you get a does not except file:// error
if os.path.isabs(web_page):
web_page = os.path.relpath(web_page)
url = QtCore.QUrl(web_page)
self.load(url)
self.frame = self.page().mainFrame()
self.frame.addToJavaScriptWindowObject("foo", self.foo)
# end loadPage
# end class LoginWindow
class LoginConnector(QObject):
#pyqtSlot()
def new_window(self):
self.dialog = QDialog()
self.dialog.show() # or exec
# end new_window
# end class LoginConnector
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = LoginWindow()
window.show()
sys.exit(app.exec_())
This is the main application structure for PySide. PyQt should be similar.

Related

Buttons In Embed (Discord.py)

I have been trying to make a fake nitro command. I made an accept button under the embed that takes the user to a link (probably a troll GIF image or picture).
Currently, this is the code.
import discord
from discord.ext import commands
from discord_components import *
from discord_buttons_plugin import *
def __init__(self, client):
self.client = client
buttons = ButtonsClient(client)
#commands.command(name='nitro')
#commands.has_permissions(ban_members=True)
async def nitro(self,ctx, member: discord.Member = None):
if member == None:
member = ctx.author
embed = discord.Embed(title = "**You've been gifted a subscription!**",
description = f"||**{member.mention}**|| has gifted you Nitro for **1 month!**",
color = 0xc17ce0)
embed.set_image(url = 'https://media.threatpost.com/wp-content/uploads/sites/103/2021/04/19145523/Discord-Nitro-e1618858537976.png' )
await buttons.send(
content = None,
embed = embed,
channel = ctx.channel.id,
components = [
ActionRow([
Button(
style = ButtonType().Link,
label = "Accept",
url = "https://c.tenor.com/Bvb1iMhQQUUAAAAC/gorilla-middle-finger.gif"
)
])
]
)
It’s not showing any error, but the command is not working. How can I do it?
Those are third-party APIs which are similar to discord.py. For using interactions and buttons in discord.py, you can use Discord's master version which can be downloaded by doing:
pip install -U git+https://github.com/Rapptz/discord.py
Support regarding that will be available at their Official Support server.

Login working in Splash API but not when SplashRequest is used

Relatively new to Splash. I'm trying to scrape a website which needs a login. I started off with the Splash API for which I was able to login perfectly. However, when I put my code in a scrapy spider script, using SplashRequest, it's not able to login.
import scrapy
from scrapy_splash import SplashRequest
class Payer1Spider(scrapy.Spider):
name = "payer1"
start_url = "https://provider.wellcare.com/provider/claims/search"
lua_script = """
function main(splash,args)
assert(splash:go(args.url))
splash:wait(0.5)
local search_input = splash:select('#Username')
search_input:send_text('')
local search_input = splash:select('#Password')
search_input:send_text('')
assert(splash:wait(0.5))
local login_button = splash:select('#btnSubmit')
login_button:mouse_click()
assert(splash:wait(7))
return{splash:html()}
end
"""
def start_requests(self):
yield SplashRequest(self.start_url, self.parse_result,args={'lua_source': self.lua_script},)
def parse_result(self, response):
yield {'doc_title' : response.text}
The output HTML is the login page and not the one after logging in.
You have to add endpoint='execute' to your SplashRequest to execute the lua-script:
yield SplashRequest(self.start_url, self.parse_result, args={'lua_source': self.lua_script}, endpoint='execute')
I believe you don't need splash to login to the site indeed. You can try next:
Get https://provider.wellcare.com and then..
# Get request verification token..
token = response.css('input[name=__RequestVerificationToken]::attr(value)').get()
# Forge post request payload...
data = [
('__RequestVerificationToken', token),
('Username', 'user'),
('Password', 'pass'),
('ReturnUrl', '/provider/claims/search'),
]
#Make dict from list of tuples
formdata=dict(data)
# And then execute request
scrapy.FormRequest(
url='https://provider.wellcare.com/api/sitecore/Login',
formdata=formdata
)
Not completely sure if all of this will work. But you can try.

Scrapy does not extract data

I am trying to get some technical informations about automobiles from this page
Here is my current code:
import scrapy
import re
from arabamcom.items import ArabamcomItem
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
class BasicSpider(CrawlSpider):
name="arabamcom"
allowed_domains=["arabam.com"]
start_urls=['https://www.arabam.com/ikinci-el/otomobil']
rules=(Rule(LinkExtractor(allow=(r'/ilan')),callback="parse_item",follow=True),)
def parse_item(self,response):
item=ArabamcomItem()
item['fiyat']=response.css('span.color-red.font-huge.bold::text').extract()
item['marka']=response.css('p.color-black.bold.word-break.mb4::text').extract()
item['yil']=response.xpath('//*[#id="js-hook-appendable-technicalPropertiesWrapper"]/div[2]/dl[1]/dd/span/text()').extract()
And this is my items.py file
import scrapy
class ArabamcomItem(scrapy.Item):
fiyat=scrapy.Field()
marka=scrapy.Field()
yil=scrapy.Field()
When i run the code i can get data from 'marka' and 'fiyat' item but spider does not get anything for 'yil' attribute. Also other parts like 'Yakit Tipi','Vites Tipi' etc. How can i solve this problem ?
What's wrong:
//*[#id="js-hook-appendable-technicalPropertiesWrapper"]/......
This id start with js and may be dynamic element appeded by javascript
Scrapy do not have the ability to render javascript by default.
There are 2 solutions you can try
Scrapy-Splash
This is a javascript rendering engine for scrapy
Install Splash as a Docker container
Modify your settings.py file to integrate splash (append following middlewares to your project)
SPLASH_URL = 'http://127.0.0.1:8050'
SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware':100,
}
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware':723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
Replace your Request Function with SplashRequest
from scrapy_splash import SplashRequest as SP
SP(url=url, callback=parse, endpoint='render.html', args={'wait': 5})
Selenium WebDriver
This is a browser automation-testing framework
Install Selenium from PyPi and install there corresponding driver(e.g. Firefox -> Geckodriver) to PATH folder
Append following middleware class to your project's middleware.py file:
class SeleniumMiddleware(object):
#classmethod
def from_crawler(cls, crawler):
middleware = cls()
crawler.signals.connect(middleware.spider_opened, signals.spider_opened)
crawler.signals.connect(middleware.spider_closed, signals.spider_closed)
return middleware
def process_request(self, request, spider):
request.meta['driver'] = self.driver
self.driver.get(request.url)
self.driver.implicitly_wait(2)
body = to_bytes(self.driver.page_source)
return HtmlResponse(self.driver.current_url, body=body, encoding='utf-8', request=request)
def spider_opened(self, spider):
"""Change your browser mode here"""
self.driver = webdriver.Firefox()
def spider_closed(self, spider):
self.driver.close()
Modify your settings.py file to integrate the Selenium middleware (append following middleware to your project and replace yourproject with your project name)
DOWNLOADER_MIDDLEWARES = {
'yourproject.middlewares.SeleniumMiddleware': 200
}
Comparison
Scrapy-Splash
An official module by Scrapy Company
You can deploy splash instance to cloud, so that you will be able to browse the url in cloud then transfer the render.html back to your spider
It's slow
Splash container will stop if there is a memory leak. (Be sure to deploy splash instance on a high memory cloud instance)
Selenium web driver
You have to have Firefox or Chrome with their corresponding automated-test-driver on your machine, unless you use PhantomJS.
You can't modify request headers directly with Selenium web driver
You could render the webpage using a headless browser but this data can be easily extracted without it, try this:
import re
import ast
...
def parse_item(self,response):
regex = re.compile('dataLayer.push\((\{.*\})\);', re.DOTALL)
html_info = response.xpath('//script[contains(., "dataLayer.push")]').re_first(regex)
data = ast.literal_eval(html_info)
yield {'fiyat': data['CD_Fiyat'],
'marka': data['CD_marka'],
'yil': data['CD_yil']}
# output an item with {'fiyat': '103500', 'marka': 'Renault', 'yil': '2017'}

How to restrict image file extension on Plone?

I have a Plone application in which I can upload images, which are ATImages. I want to validate the extension file (mainly to forbid pdf files). There are created with a url call like http://blablba.com/createObject?type_name=Image
I have tried setting the /content_type_registry with file extensions associated with images, with no success (pdf upload still work)
I guess I could write a new class extending ATImages, create a form with a validator, but it looks a little bit complicated and it seemed that some settings on content_type registry would be enough (or elsewhere).
How would you do that ? (forbid pdf ?)
thx
We had a similar problem.
Archetypes fires several events during its magic, amongst others a "post validation event" (IObjectPostValidation). This way we added a check for the content-type.
subscriber (zcml):
<subscriber provides="Products.Archetypes.interfaces.IObjectPostValidation"
factory=".subscribers.ImageFieldContentValidator" />
quick and dirty implementation:
from Products.Archetypes.interfaces.field import IImageField
from plone.app.blob.interfaces import IBlobImageField
from Products.Archetypes.interfaces import IObjectPostValidation
from zope.interface import implements
from zope.component import adapts
# import your message factory as _
ALLOWED_IMAGETYPES = ['image/png',
'image/jpeg',
'image/gif',
'image/pjpeg',
'image/x-png']
class ImageFieldContentValidator(object):
"""Validate that the ImageField really contains a Imagefile.
Show a Errormessage if it doesn't.
"""
implements(IObjectPostValidation)
adapts(IBaseObject)
img_interfaces = [IBlobImageField, IImageField]
msg = _(u"error_not_image",
default="The File you wanted to upload is no image")
def __init__(self, context):
self.context = context
def __call__(self, request):
for fieldname in self.context.Schema().keys():
field = self.context.getField(fieldname)
if True in [img_interface.providedBy(field) \
for img_interface in self.img_interfaces]:
item = request.get(fieldname + '_file', None)
if item:
header = item.headers
ct = header.get('content-type')
if ct in ALLOWED_IMAGETYPES:
return
else:
return {fieldname: self.msg}

QWebView Auto Tabs

I open a web page with QWebView.load(QUrl(myurl)) , the webpage gets some input and returns a new php generated page.
If executed in Firefox the browser automatically opens a new tab/window to show the returned page.
How to tell QWebView to open a new instance of QWebview with the returned data loaded?
I was looking at at the QwebView documentation at
www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qwebview.html ... but no joy.
Example of such a page :
http://www.iqfront.com/index.php?option=com_content&view=article&id=5&Itemid=4
Thanks for any ideas.
from my understanding this is developer's job to create and open new tabs for urls clicked.You would need to define a custom slot for QWebView::linkClicked signal. This signal is emitted whenever the user clicks on a link and the page's linkDelegationPolicy property is set to delegate the link handling for the specified url. There you can create a new instance of QWebView add it a tab and open new url there. Below is an example:
import sys
from PyQt4 import QtGui, QtCore, QtWebKit
class MainForm(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainForm, self).__init__(parent)
self.tabWidget = QtGui.QTabWidget(self)
self.setCentralWidget(self.tabWidget)
self.loadUrl(QtCore.QUrl('http://qt.nokia.com/'))
def loadUrl(self, url):
view = QtWebKit.QWebView()
view.connect(view, QtCore.SIGNAL('loadFinished(bool)'), self.loadFinished)
view.connect(view, QtCore.SIGNAL('linkClicked(const QUrl&)'), self.linkClicked)
view.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks)
self.tabWidget.setCurrentIndex(self.tabWidget.addTab(view, 'loading...'))
view.load(url)
def loadFinished(self, ok):
index = self.tabWidget.indexOf(self.sender())
self.tabWidget.setTabText(index, self.sender().url().host())
def linkClicked(self, url):
self.loadUrl(url)
def main():
app = QtGui.QApplication(sys.argv)
form = MainForm()
form.show()
app.exec_()
if __name__ == '__main__':
main()
hope this helps, regards

Resources