A British find-a-movie challenge

1

1

This is a more difficult version of It's a find-a-movie challenge .

Input

Your code should take a BBFC rating and a number from 1 to 5 as input. It can do this in any way you find convenient.

Output

Your code should return the name of any movie which has a) that film rating and b) that number of stars in a Guardian film review.

If there is no such movie it can output anything you like.

The possible BBFC film ratings are U, PG, 12, 12A, 15, 18, R18, TBC.

Your code may report one or more movies, that is up to you.

To clarify, your code is meant to access the web to get the answers to queries.

Example

Say the input is U, 5 then your code could output "My Neighbour Totoro".

Please show an example of your code working with the film rating PG and score 4 along with your answer.

Notes

The Guardian does have an API but this requires registration. For this challenge you may not use it.

Example code

The following Python 3 code gets all the movies along with their score out of 5, although not 100% perfectly.

from bs4 import BeautifulSoup
import requests
import sys

for i in range(1,837):
    print("Page", i,file=sys.stderr)
    result = requests.get("https://www.theguardian.com/film+tone/reviews?page={0}".format(i))
    data = result.text
    soup = BeautifulSoup(data, "lxml")

    tags = soup.find_all("div", {"class":"stars"})

    for tag in tags:
        stars = 0
        for star in tag.find_all("span", {"class":"star__item--grey"}):
            stars +=1
        main = tag.parent
        title = main.find("h2")
        if title:
            a = title.find("span", {"class":"js-headline-text"})
            print("{} - {}".format(5 - stars, a.text))

user9206

Posted 2017-09-26T16:29:15.947

Reputation:

Answers

2

NodeJS

I'm an awful golfer tho

The inputs must be passed like this node filename 12,12A,15,18 4 for fetching a movie with one of the ratings comma separated and at least 4 stars

var fetch=require('node-fetch');
var {JSDOM, VirtualConsole}=require('jsdom');

var f=x=>fetch(x).then(r=>r.text());
var vc = new VirtualConsole(); // ignore annoying css errors
var [bbfc='U,PG,12',stars='3']=process.argv.slice(2);

var Z=async()=>{
    for(var i=0;i<10;i++){ // 10 max pages, can be anything
        var t= await f(`https://www.theguardian.com/film+tone/reviews?page=${i}`);
        var w=new JSDOM(t, {virtualConsole:vc}).window;
        for(var h of w.document.querySelectorAll('.fc-item__header')){
            if (h.querySelectorAll('.star__item--golden').length>=stars){
                var title=h.querySelector('.js-headline-text').textContent.split(' review')[0].trim();
                var t=await f('http://www.bbfc.co.uk/search/releases/'+title);
                var rating=t.match(/BBF\w_(\w+)_/)[1];
                if(bbfc.includes(rating)) return title;
            }
        }
    }
};

Z()
.then(console.log)
.catch(console.error)

caub

Posted 2017-09-26T16:29:15.947

Reputation: 146

2At least you can remove lots of unnecessary whitespaces, and you must also include the bytecount. – Erik the Outgolfer – 2017-09-30T15:57:54.210

That's 956 bytes, but removing whitespaces could save you some. – RedClover – 2017-09-30T16:01:29.877

It works! However the question asks for exactly the right score, not at least the score. – None – 2017-09-30T17:58:24.017

I found a bug I think. Try node caub.js U 4. You get Peter Bradshaw's film of the week Daphne. First, Daphne is rated 15 and second you need to extract the movie name. – None – 2017-09-30T18:22:58.783

The code crashes on page 28 with TypeError: Cannot read property '1' of null at Z (/home/foo/caub.js:17:51) at process._tickCallback (internal/process/next_tick.js:109:7) – None – 2017-09-30T21:04:22.407

On page 22, the code returns "The Florida Project" as a "U" rated movie but it isn't rated at all yet by the BBFC as far as I can tell and it's R rated in the US so it can't be right. See e.g. http://www.bbfc.co.uk/search/releases/The%2BFlorida%2BProject . I general it might give the wrong answer for movies for which the BBFC has no rating.

– None – 2017-09-30T21:06:27.040

instead of var variable;var variable, use var variable,variable,variable. and get rid of whitespace. – Brian H. – 2017-10-05T15:07:59.367

1

Javascript/JQuery - 517 504 494 bytes

Not really golfed at all, just wanted to write an answer.

x=>y=>{t=n=i=1;f=()=>{if(t){$.get("https://www.theguardian.com/film+tone/reviews?page="+i,d=>{l=$(d).find("div.stars").toArray().slice(1);for(k=0;k<l.length&&t;k++){((j,m)=>($.get('http://www.bbfc.co.uk/search/releases/'+encodeURI(n=$(m[j].parentNode).find("h2 span.js-headline-text").text().split(" review")[0]),(p=>b=>{if(/BBFC_(.*?)_/.exec($(b).find(".symbol img")[0].src)[1]==y&&$(m[j]).find(".star__item--golden").length==x){if(t)alert(p);t=0}})(n))))(k,l)}});i++;setTimeout(f,2000)}};f()}

It waits 10 sec before trying another page to stop the program from doing too many requests concurrently, so it may take some time with some inputs.

Examples:

enter image description here

enter image description here

Maltysen

Posted 2017-09-26T16:29:15.947

Reputation: 25 023

I don't know JS, but I do know that x=>y=> using currying is a byte shorter than (x,y)=>. – LyricLy – 2017-09-30T04:07:01.287

Thank you for giving the first answer! Is it possible to make a https://tio.run/# link for it?

– None – 2017-09-30T06:13:53.130

@Lembik TIO cannot access the internet. Since this is JS, a Stack Snippet could be used, or it's reasonably easy to run the code in your browser's console. – LyricLy – 2017-09-30T06:50:48.513

since when jquery is allowed in golfing? use fetch – caub – 2017-09-30T12:53:54.793

Can you show an example of your code running? I am having no luck getting it to work. My steps: open new tab, press F12, enter f=(x,y)..., f("U",5) . Then f("U",5) gives me TypeError: $.get is not a function [Learn More] – None – 2017-09-30T12:57:55.880

@caub as it's included in the language of the answer, it's allowed to be used. It's the same as using libraries in other languages. – dzaima – 2017-09-30T12:58:43.343

@dzaima Wasn't the complaint that it is one character longer? – None – 2017-09-30T12:59:30.070

@Lembik that's cuz you don't have jquery. Easiest way is to just run it in the console on http://jquery.com. Also, you'll need to disable cors if you're running it in the browser

– Maltysen – 2017-09-30T18:15:47.557

@Lembik added examples – Maltysen – 2017-09-30T18:22:14.770

1

Python + BS4 - 631 bytes

Lembik wanted a Python answer so he could run it, so I made one, but its way longer.

from bs4 import BeautifulSoup as b
import requests
def f(x,y):
 i=n=1
 while 1:
  for m in b(requests.get("https://www.theguardian.com/film+tone/reviews?page="+`i`).text,'lxml').find_all('div',{'class':'stars'}):
         a=m.parent.find('h2')
         if a:
          e=a.find('span',{'class':'js-headline-text'}).text.split(" review")[0]
          s=b(requests.get('http://www.bbfc.co.uk/search/releases/'+requests.utils.quote(e)).text,'lxml').find("p",{"class":"symbol"})
          if s and s.find("img").get('src').split("BBFC_")[1].split("_")[0]==y and len(m.find_all('span',{'class':'star__item--golden'}))==x:return e
  i+=1

Maltysen

Posted 2017-09-26T16:29:15.947

Reputation: 25 023

The code crashes on page 6 with "Traceback (most recent call last): File "guardianfilm-2.py", line 17, in <module> print f(5, "U") File "guardianfilm-2.py", line 13, in f if s and s.find("img").get('src').split("BBFC_")[1].split("_")[0]==y and len(m.find_all('span',{'class':'star__item--golden'}))==x: IndexError: list index out of range " – None – 2017-10-01T09:26:04.330

621 bytes with a bit of reordering and link tweaking. – Mr. Xcoder – 2017-10-01T20:47:38.743

@Mr.Xcoder You can save a few bytes by optimizing indentation.

– Jonathan Frech – 2017-10-02T22:05:28.127

Is the variable n used at all in your code? – None – 2017-10-21T20:30:44.370