I am getting a HTML in a key of JSON response from API call. I load that HTML on UIWebView.
Everything is displayed but with "twitter-tweet" tag the view is not being created as tweet only text is shown.
this is how i want to display on the simulaor but
This is how its being displayed.
The HTML which is coming like this
This way worked for me, please go step by step
Sample Twitter Resonse HTML Look like (Remove " in text to make correct string)
let responseTwitterHTMLContent = " <blockquote class=\"twitter-tweet\" data-width=\"500\">\n<p lang=\"en\" dir=\"ltr\"><a href=\"https:\/\/twitter.com\/kalyansury\">#kalyansury<\/a> Yes, last night. With a really lame and bleeding obvious response. I'm thinking of my next steps. <a href=\"https:\/\/twitter.com\/HDFC_Bank\">#HDFC_Bank<\/a> <a href=\"https:\/\/twitter.com\/HDFCBank_Cares\">#HDFCBank_Cares<\/a><\/p>\n<p>— Karthik (#beastoftraal) <a href=\"https:\/\/twitter.com\/beastoftraal\/status\/826589530748813313\">February 1, 2017<\/a><\/p><\/blockquote> "
If your response doesn't include this twitter script
<script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>
Include twitter script like below in head tag programatically
<head><script async src=//platform.twitter.com/widgets.js charset=utf-8></script></head>
then final Modified HTML content look like
let ModifyHtmlcontent = "<html><head><script async src=//platform.twitter.com/widgets.js charset=utf-8></script><style></head><body style = width: 100%; height:auto; overflow:hidden; margin:100px; text-align:justify;>\(responseTwitterHTMLContent)</body></html>"
Load this content in webview
If I load above html it doesn't show twitter format look coz twitter script which we included above not downloaded by uiwebview for that you need to give base url https:
let url: URL = URL(string: "https:")!
self.yourWebView.loadHTMLString(ModifyHtmlcontent, baseURL: url)
If base url is creating problem then change the script add https: directly in twitter script And make base url to nil
<head><script async src=https://platform.twitter.com/widgets.js charset=utf-8></script></head>
self.yourWebView.loadHTMLString(ModifyHtmlcontent, baseURL: nil)
make sure you have given script async
Happy Coding!
Reference
Related
I have a method to parse website with using Swiftsoup go get the price of a product:
#objc func actionButtonTapped(){
let url = "https://www.overkillshop.com/de/c2h4-interstellar-liaison-panelled-zip-up-windbreaker-r001-b012-vanward-black-grey.html"
let url2 = "https://www.asos.com/de/asos-design/asos-design-schwarzer-backpack-mit-ringdetail-und-kroko-muster/prd/14253083?clr=schwarz&colourWayId=16603012&SearchQuery=&cid=4877"
do {
let html: String = getHTMLfromURL(url: url2)
let doc: Document = try SwiftSoup.parse(html)
let priceClasses: Elements = try doc.select("[class~=(?i)price]")
for priceClass: Element in priceClasses.array() {
let priceText : String = try priceClass.text()
print(try priceClass.className())
print("pricetext: \(priceText)")
}
} catch Exception.Error(let type, let message) {
print(message)
} catch {
print("error")
}
}
The method works fine for url but for url2 it is not printing all all the classNames even though they match the regex. This is where the price actually is:
<span data-id="current-price" data-bind="text: priceText(), css: {'product-price-discounted' : isDiscountedPrice }, markAndMeasure: 'pdp:price_displayed'" class="current-price">36,99 €</span>
The output of the function is this:
product-price pricetext:
stock-price-retry-oos
pricetext:
stock-price-retry
pricetext:
It is not printing class=current-price. Is something wrong with my regex or why does it not find that class??
EDIT:
I found out that the price is not actually inside the HTML of url2. Only the classes that are actually printed out are inside. What's the reason for that and how can I solve that?
The html is not static. It can change over time. If you make a get request to the site's URL you will get the initial value of the html for that site.
But on browsers there is this thing, called javascript, that can make the page's HTML change over time. It's quite common actually:
- The site gets loaded at first with some javascript
- The javascript (developed by the site's creator) than runs and does stuff
- Content dynamically changes by calling some API by that javascript
You can't scrape that content by HTML scraping of the base URL.
If you ask me how I'd do that anyway, is by looking for the site's HTTP requests where it gets the content. Look at that API and use that API myself. Get the data, and store it in some of my servers.
Than on the client I call my server's API to get that data.
Also I'm not really sure that's legal.
But, as far as I understood by your last couple questions, you don't want to do that.
If you really need to do that on the client, you can use WKWebView, load the page, wait for the content to show up, and then get the current HTML of the page by doing something like this:
webView.evaluateJavaScript("document.documentElement.outerHTML.toString()",
completionHandler: { (html: Any?, error: Error?) in
print(html)
})
Look at this answer for more about this.
I hope this solves all of your problem, because I think I don't have much more time to help you :D
I am trying to find sign in link via scrapy crawler on any website, for example www.microsoft.com. However when I get initial response from the website the sign in link isn't present. But when I visit the website I am able to see the sign in link in the "View Source".
The code is written to get all the links by checking for <a> tag in response using xpath. There are other links that are present in response, however the sign in link is not visible.
for links in response.xpath("//a"): ---> to get the links
if links.xpath("#href").extract() and links.xpath("#href").extract()[0]:
link = links.xpath("#href").extract()[0]
if(link.startswith("http")):
searched_url = link
else :
if(link.startswith("/")):
link = link[1:len(link)]
searched_url = response.url + link
all_other_urls.append(searched_url)
print(searched_url) ---> printing the links present in the response.
The response I receive has link present in this manner (refer signInUrl). :
<div id="meControl" class="c-me" data-signinsettings='{"containerId":"meControl","enabled":true,"headerHeight":48,"debug":false,"extensibleLinks":[],"userData":{"idp":"msa","firstName":"","lastName":"","memberName":"","cid":"","authenticatedState":"3"},"rpData":{"preferredIdp":"msa","msaInfo":{"signInUrl":"https://www.microsoft.com/mscomhp/onerf/signin?EEL=True\u0026pcexp=True","signOutUrl":"https://www.microsoft.com/mscomhp/onerf/signout?pcexp=True","meUrl":"https://login.live.com/me.srf?wa=wsignin1.0"},"aadInfo":{"signOutUrl":"https://www.microsoft.com/mscomhp/onerf/signout?pcexp=True","appId":"","siteUrl":"","blockMsaFed":true}}}' data-m='{"cN":"GlobalNav_Account_cont","cT":"Container","id":"c6c1c7c2m1r1a1","sN":6,"aN":"c1c7c2m1r1a1"}'>
<div class="msame_Header">
<div class="msame_Header_name st_msame_placeholder">Sign in</div>
</div>
My code will work if the link is present in <a> tag which I can see on website view source:
a class="mectrl_resetStyle mectrl_trigger" id="mectrl_main_trigger" aria-label="Sign in to your account" href="https://www.microsoft.com/mscomhp/onerf/signin?EEL=True&pcexp=True&ru=https%3A%2F%2Fwww.microsoft.com%2Fen-us%2F" target="_top"><div class="mectrl_header" aria-hidden="true"><div class="mectrl_headertext mectrl_truncate"> Sign in /div> div class="mectrl_profilepic mectrl_glyph glyph_signIn_circle" id="mectrl_headerPicture" role="presentation" aria-hidden="true"></div></div></a
You can find the signin-url without rendering the page as follows:
import json
signin_settings = response.xpath('//*[#id="meControl"]/#data-signinsettings').extract_first()
signin_d = json.loads(signin_settings)
signin_url = signin_d['rpData']['msaInfo']['signInUrl']
Note: This is about JavaFX WebView, not Android WebView (i. e. I have seen "Android Webview Anchor Link (Jump link) not working").
I display a generated HTML page inside a javafx.scene.web.WebView that contains anchors and links to those anchors like this:
<p>Jump to Introduction</p>
some text ...
<h1 id="introduction">Introduction</h1>
more text ...
I use this code to load the HTML into the WebView:
public void go(String location) {
try {
// read the content into a String ...
String html = NetUtil.readContent(new URL(location), StandardCharsets.UTF_8);
// ... and use loadContent()
webview.getEngine().loadContent(html);
} catch (IOException e) {
LOG.error(e);
}
}
Everything is rendered correctly, but if I click on the link named "Introduction", nothing happens.
The HTML however is correct, which I checked by instead using this code:
public void go(String location) {
// use load() to directly load the URL
webview.getEngine().load(location);
}
Now, everything worls fine.
The problem seems to be somehow because the document URL of the WebView is null when using loadContent(), but since it's a readonly property, I have no idea how to make it work.
I need to use loadContent(), because the HTML is generated on the fly, and if possible in any way, I don't want to have to write it out to a file just to make anchor links working. Is there a way to fix this?
EDIT
I filed a bug for JavaFX.
It's probably another WebEngine bug. A lot of that code is just a native libraries wrapped in api, so we can't modify it in runtime to fix some disabilities.
If you are able to change the structure of generated file you can implement scrolling to element in js:
<script>
function scrollTo(elementId) {
document.getElementById(elementId).scrollIntoView();
}
</script>
<a href='#' onclick=scrollTo('CX')>Jump to Chapter X</a>
<h2 id="CX">Chapter X</h2>
If you can't change the structure, there is some steps that I've made to try to fix it and some suggestions - at first I've set value of location by reflections after loadContent for sure:
Field locationField = WebEngine.class.getDeclaredField("location");
locationField.setAccessible(true);
ReadOnlyStringWrapper location = (ReadOnlyStringWrapper) locationField.get(engine);
location.set("local");
But in fact, keeping state of actual location is just an information for you and manipulating this changes nothing. I've also found a way to set url from js (just a long shot, we don't have any specific details why it's not working):
window.history.pushState("generated", "generated", '/generated');
Of course we can't because of:
SecurityError: DOM Exception 18: An attempt was made to break through the security policy of the user agent.
I think you should forget about loadContent(). You said that you didn't want to write generated content to file. A little dirty hack but really helpful for you could be wrapped http server on random and unused port in your application. You don't even need external libraries because Java has simple utilities like that:
HttpServer server = HttpServer.create(new InetSocketAddress(25000), 0);
server.createContext("/generated", httpExchange -> {
String content = getContent();
httpExchange.sendResponseHeaders(200, content.length());
OutputStream os = httpExchange.getResponseBody();
os.write(content.getBytes());
os.close();
});
server.setExecutor(null);
server.start();
You can also use another browser to display your page, e.g. JCEF (Java Chromium Embedded Framework).
I want to send a clickable link to gmail message body and google plus message while sharing in iOS.I have tried many ways with HTML.But end up with issue
Now I m using below string to mail message body:
I m getting the output as shown in picture but link in mail is not clickable.
I am setting the message body as:
[self.globalMailComposer setMessageBody:message isHTML:YES];
Can any please let me know where am I going wrong
thanks in advance
Just replace your link with href
<a href='your link should be here'>Open This</a>
For example :
NSString *link = [NSString stringWithFormat:#"http://www.google.com"];
[controller setMessageBody:[NSString stringWithFormat:#"<a href=%#>%#</a>",link,#"Google"] isHTML:YES];
I have a sidepanel, its code get data uri image from server (specifically from a Google Docs, by using google.script.run).
I need to display it, I'm trying to do so on an IMG tag in the HTML document, but the sandbox forbid to assign anything to img.src .
Any ideas, instead of using templates? Because I want to change the image dynamically.
Thank you
If you are working inHtmlService.SandboxMode.IFRAME mode you can pass the base64 to the image src. Below is an example of using a template to do this.
code.gs
function doGet() {
var t = HtmlService.createTemplateFromFile('index');
t.icon = icon;
return t.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
index.html
<div>
<img src="data:image/png;base64,<?=icon?>"/>
</div>
icons.gs
var icon = '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';