├── configure.py ├── google-sheets ├── sheets-api.py └── football_news.csv ├── convert-speech-to-text.py ├── real-time-speech-recognition.py ├── audio-summarization.ipynb └── speech-to-text.ipynb /configure.py: -------------------------------------------------------------------------------- 1 | auth_key = "your-api-token" 2 | -------------------------------------------------------------------------------- /google-sheets/sheets-api.py: -------------------------------------------------------------------------------- 1 | import gspread 2 | from oauth2client.service_account import ServiceAccountCredentials 3 | import pandas as pd 4 | 5 | # Connect to Google 6 | # Scope: Enable access to specific links 7 | scope = ['https://www.googleapis.com/auth/spreadsheets', 8 | "https://www.googleapis.com/auth/drive"] 9 | 10 | credentials = ServiceAccountCredentials.from_json_keyfile_name("gs_credentials.json", scope) 11 | client = gspread.authorize(credentials) 12 | 13 | # Create a blank spreadsheet (Note: We're using a service account, so this spreadsheet is visible only to this account) 14 | sheet = client.create("NewDatabase") 15 | 16 | # To access newly created spreadsheet from Google Sheets with your own Google account you must share it with your email 17 | # Sharing a Spreadsheet 18 | sheet.share('your_email_goes_here', perm_type='user', role='writer') 19 | 20 | # Open the spreadsheet 21 | sheet = client.open("NewDatabase").sheet1 22 | # read csv with pandas 23 | df = pd.read_csv('football_news.csv') 24 | # export df to a sheet 25 | sheet.update([df.columns.values.tolist()] + df.values.tolist()) 26 | -------------------------------------------------------------------------------- /convert-speech-to-text.py: -------------------------------------------------------------------------------- 1 | # STEP 1: UPLOAD YOUR AUDIO FILE AND GET URL 2 | import requests 3 | import os 4 | import sys 5 | import time 6 | 7 | filename = # Your path goes here 8 | api_key = # Your API key goes here 9 | upload_endpoint = 'https://api.assemblyai.com/v2/upload' 10 | 11 | def read_file(filename, chunk_size=5242880): 12 | with open(filename, 'rb') as f: 13 | while True: 14 | data = f.read(chunk_size) 15 | if not data: 16 | break 17 | yield data 18 | 19 | 20 | headers = {'authorization': api_key, 21 | 'content-type': 'application/json'} 22 | response = requests.post(upload_endpoint, 23 | headers=headers, 24 | data=read_file(filename)) 25 | 26 | audio_url = response.json()['upload_url'] 27 | 28 | # STEP 2: GET THE TRANSCRIPT REQUEST 29 | transcript_endpoint = "https://api.assemblyai.com/v2/transcript" 30 | 31 | response = requests.post(transcript_endpoint, 32 | headers=headers, 33 | json={ 34 | "audio_url": audio_url, 35 | }) 36 | transcript_id = response.json()['id'] 37 | 38 | # STEP 3: CHECK OUT THE STATUS AND GET THE TRANSCRIPT 39 | polling_endpoint = os.path.join(transcript_endpoint, transcript_id) 40 | 41 | status = '' 42 | while status != 'completed': 43 | response_result = requests.get( 44 | polling_endpoint, 45 | headers=headers 46 | ) 47 | status = response_result.json()['status'] 48 | print(f'Status: {status}') 49 | 50 | if status == 'error': 51 | sys.exit('Audio file failed to process.') 52 | elif status != 'completed': 53 | time.sleep(5) 54 | 55 | 56 | if status == 'completed': 57 | transcript = response_result.json()['text'] 58 | print(transcript) 59 | 60 | with open('transcript.txt', 'w') as f: 61 | f.write(transcript) -------------------------------------------------------------------------------- /real-time-speech-recognition.py: -------------------------------------------------------------------------------- 1 | import websockets 2 | import asyncio 3 | import base64 4 | import json 5 | from configure import auth_key 6 | 7 | import pyaudio 8 | 9 | FRAMES_PER_BUFFER = 3200 10 | FORMAT = pyaudio.paInt16 11 | CHANNELS = 1 12 | RATE = 16000 13 | p = pyaudio.PyAudio() 14 | 15 | # starts recording 16 | stream = p.open( 17 | format=FORMAT, 18 | channels=CHANNELS, 19 | rate=RATE, 20 | input=True, 21 | frames_per_buffer=FRAMES_PER_BUFFER 22 | ) 23 | 24 | # the AssemblyAI endpoint we're going to hit 25 | URL = "wss://api.assemblyai.com/v2/realtime/ws?sample_rate=16000" 26 | 27 | async def send_receive(): 28 | 29 | print(f'Connecting websocket to url ${URL}') 30 | 31 | async with websockets.connect( 32 | URL, 33 | extra_headers=(("Authorization", auth_key),), 34 | ping_interval=5, 35 | ping_timeout=20 36 | ) as _ws: 37 | 38 | await asyncio.sleep(0.1) 39 | print("Receiving SessionBegins ...") 40 | 41 | session_begins = await _ws.recv() 42 | print(session_begins) 43 | print("Sending messages ...") 44 | 45 | 46 | async def send(): 47 | while True: 48 | try: 49 | data = stream.read(FRAMES_PER_BUFFER) 50 | data = base64.b64encode(data).decode("utf-8") 51 | json_data = json.dumps({"audio_data":str(data)}) 52 | await _ws.send(json_data) 53 | 54 | except websockets.exceptions.ConnectionClosedError as e: 55 | print(e) 56 | assert e.code == 4008 57 | break 58 | 59 | except Exception as e: 60 | assert False, "Not a websocket 4008 error" 61 | 62 | await asyncio.sleep(0.01) 63 | 64 | return True 65 | 66 | 67 | async def receive(): 68 | while True: 69 | try: 70 | result_str = await _ws.recv() 71 | print(json.loads(result_str)['text']) 72 | 73 | except websockets.exceptions.ConnectionClosedError as e: 74 | print(e) 75 | assert e.code == 4008 76 | break 77 | 78 | except Exception as e: 79 | assert False, "Not a websocket 4008 error" 80 | 81 | send_result, receive_result = await asyncio.gather(send(), receive()) 82 | 83 | while True: 84 | asyncio.run(send_receive()) 85 | -------------------------------------------------------------------------------- /audio-summarization.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "8b08b5bd", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "# STEP 1: UPLOAD YOUR AUDIO FILE AND GET URL\n", 11 | "import requests\n", 12 | "\n", 13 | "filename = '/Users/frankandrade/Desktop/Steve Jobs.mp3' # Your path goes here\n", 14 | "# api_key = # Your API key goes here\n", 15 | "upload_endpoint = 'https://api.assemblyai.com/v2/upload'\n", 16 | "\n", 17 | "def read_file(filename, chunk_size=5242880):\n", 18 | " with open(filename, 'rb') as f:\n", 19 | " while True:\n", 20 | " data = f.read(chunk_size)\n", 21 | " if not data:\n", 22 | " break\n", 23 | " yield data\n", 24 | "\n", 25 | "\n", 26 | "headers = {'authorization': api_key,\n", 27 | " 'content-type': 'application/json'}\n", 28 | "response = requests.post(upload_endpoint,\n", 29 | " headers=headers,\n", 30 | " data=read_file(filename))\n", 31 | "\n", 32 | "audio_url = response.json()['upload_url']" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "id": "f359f913", 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "# STEP 2: GET THE TRANSCRIPT REQUEST\n", 43 | "transcript_endpoint = \"https://api.assemblyai.com/v2/transcript\"\n", 44 | "\n", 45 | "response = requests.post(transcript_endpoint,\n", 46 | " headers=headers,\n", 47 | " json={\n", 48 | " \"audio_url\": audio_url,\n", 49 | " \"auto_chapters\": True\n", 50 | " })\n", 51 | "transcript_id = response.json()['id']" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": 3, 57 | "id": "5536f231", 58 | "metadata": {}, 59 | "outputs": [ 60 | { 61 | "name": "stdout", 62 | "output_type": "stream", 63 | "text": [ 64 | "Status: processing\n", 65 | "Status: processing\n", 66 | "Status: processing\n", 67 | "Status: processing\n", 68 | "Status: processing\n", 69 | "Status: processing\n", 70 | "Status: processing\n", 71 | "Status: processing\n", 72 | "Status: processing\n", 73 | "Status: processing\n", 74 | "Status: processing\n", 75 | "Status: processing\n", 76 | "Status: processing\n", 77 | "Status: processing\n", 78 | "Status: processing\n", 79 | "Status: processing\n", 80 | "Status: processing\n", 81 | "Status: completed\n", 82 | "Transcript Saved\n" 83 | ] 84 | } 85 | ], 86 | "source": [ 87 | "# STEP 3: SAVE THE TRANSCRIPT AND SUMMARY\n", 88 | "import os\n", 89 | "import sys\n", 90 | "import time\n", 91 | "import json\n", 92 | "\n", 93 | "polling_endpoint = os.path.join(transcript_endpoint, transcript_id)\n", 94 | "\n", 95 | "status = ''\n", 96 | "while status != 'completed':\n", 97 | " response_result = requests.get(\n", 98 | " polling_endpoint,\n", 99 | " headers=headers\n", 100 | " )\n", 101 | " status = response_result.json()['status']\n", 102 | " print(f'Status: {status}')\n", 103 | "\n", 104 | " if status == 'error':\n", 105 | " sys.exit('Audio file failed to process.')\n", 106 | " elif status != 'completed':\n", 107 | " time.sleep(10)\n", 108 | "\n", 109 | "\n", 110 | "if status == 'completed':\n", 111 | " filename = transcript_id + '.txt'\n", 112 | " with open(filename, 'w') as f:\n", 113 | " f.write(response_result.json()['text'])\n", 114 | "\n", 115 | " filename = transcript_id + '_chapters.json'\n", 116 | " with open(filename, 'w') as f:\n", 117 | " chapters = response_result.json()['chapters']\n", 118 | " json.dump(chapters, f, indent=4)\n", 119 | "\n", 120 | " print('Transcript Saved')" 121 | ] 122 | } 123 | ], 124 | "metadata": { 125 | "kernelspec": { 126 | "display_name": "Python 3", 127 | "language": "python", 128 | "name": "python3" 129 | }, 130 | "language_info": { 131 | "codemirror_mode": { 132 | "name": "ipython", 133 | "version": 3 134 | }, 135 | "file_extension": ".py", 136 | "mimetype": "text/x-python", 137 | "name": "python", 138 | "nbconvert_exporter": "python", 139 | "pygments_lexer": "ipython3", 140 | "version": "3.8.8" 141 | }, 142 | "toc": { 143 | "base_numbering": 1, 144 | "nav_menu": {}, 145 | "number_sections": true, 146 | "sideBar": true, 147 | "skip_h1_title": false, 148 | "title_cell": "Table of Contents", 149 | "title_sidebar": "Contents", 150 | "toc_cell": false, 151 | "toc_position": {}, 152 | "toc_section_display": true, 153 | "toc_window_display": false 154 | } 155 | }, 156 | "nbformat": 4, 157 | "nbformat_minor": 5 158 | } 159 | -------------------------------------------------------------------------------- /speech-to-text.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 5, 6 | "id": "8b08b5bd", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "# STEP 1: UPLOAD YOUR AUDIO FILE\n", 11 | "import requests\n", 12 | "\n", 13 | "filename = '/Users/frankandrade/Desktop/YouTube Video Intro.mp3' # Your path goes here\n", 14 | "api_key = # Your API key goes here\n", 15 | "\n", 16 | "def read_file(filename, chunk_size=5242880):\n", 17 | " with open(filename, 'rb') as _file:\n", 18 | " while True:\n", 19 | " data = _file.read(chunk_size)\n", 20 | " if not data:\n", 21 | " break\n", 22 | " yield data\n", 23 | "\n", 24 | "\n", 25 | "headers = {'authorization': api_key}\n", 26 | "response = requests.post('https://api.assemblyai.com/v2/upload',\n", 27 | " headers=headers,\n", 28 | " data=read_file(filename))\n", 29 | "\n", 30 | "audio_url = response.json()['upload_url']" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 6, 36 | "id": "5536f231", 37 | "metadata": {}, 38 | "outputs": [ 39 | { 40 | "name": "stdout", 41 | "output_type": "stream", 42 | "text": [ 43 | "{'id': 'orehtd1kvp-20c8-4b01-ba28-1a86b810e524', 'language_model': 'assemblyai_default', 'acoustic_model': 'assemblyai_default', 'language_code': 'en_us', 'status': 'queued', 'audio_url': 'https://cdn.assemblyai.com/upload/3d48cd67-ad08-4be5-b83b-4463c8d946b4', 'text': None, 'words': None, 'utterances': None, 'confidence': None, 'audio_duration': None, 'punctuate': True, 'format_text': True, 'dual_channel': None, 'webhook_url': None, 'webhook_status_code': None, 'speed_boost': False, 'auto_highlights_result': None, 'auto_highlights': False, 'audio_start_from': None, 'audio_end_at': None, 'word_boost': [], 'boost_param': None, 'filter_profanity': False, 'redact_pii': False, 'redact_pii_audio': False, 'redact_pii_audio_quality': None, 'redact_pii_policies': None, 'redact_pii_sub': None, 'speaker_labels': False, 'content_safety': False, 'iab_categories': False, 'content_safety_labels': {}, 'iab_categories_result': {}, 'disfluencies': False, 'sentiment_analysis': False, 'sentiment_analysis_results': None, 'auto_chapters': False, 'chapters': None, 'entity_detection': False, 'entities': None}\n", 44 | "Status: processing\n", 45 | "Status: processing\n", 46 | "Status: processing\n", 47 | "Status: completed\n", 48 | "If you are thinking about making a career switch to data science or having watching tutorials to learn data science on your own. This video is for you. In this video, I will show you all the things you need to learn to become am a data scientist. I will introduce you to all the concepts you need to master from math and statistics, the programming languages you need to know as a data scientist and also the visualization tools used in data science, as well as some popular data science projects.\n" 49 | ] 50 | } 51 | ], 52 | "source": [ 53 | "# STEP 2: SUBMIT YOUR UPLOAD FOR TRANSCRIPTION\n", 54 | "import os\n", 55 | "import sys\n", 56 | "import time\n", 57 | "\n", 58 | "endpoint = \"https://api.assemblyai.com/v2/transcript\"\n", 59 | "json = { \"audio_url\": audio_url }\n", 60 | "headers = {\n", 61 | " \"authorization\": api_key,\n", 62 | " \"content-type\": \"application/json\"\n", 63 | "}\n", 64 | "response = requests.post(endpoint, json=json, headers=headers)\n", 65 | "response_json = response.json()\n", 66 | "print(response_json)\n", 67 | "\n", 68 | "# STEP 3: CHECK OUT THE STATUS AND GET THE TRANSCRIPT\n", 69 | "\n", 70 | "status = ''\n", 71 | "while status != 'completed':\n", 72 | " response_result = requests.get(\n", 73 | " os.path.join(endpoint, response_json['id']),\n", 74 | " headers=headers\n", 75 | " )\n", 76 | " status = response_result.json()['status']\n", 77 | " print(f'Status: {status}')\n", 78 | "\n", 79 | " if status == 'error':\n", 80 | " sys.exit('Audio file failed to process.')\n", 81 | " elif status != 'completed':\n", 82 | " time.sleep(5)\n", 83 | "\n", 84 | "transcript = response_result.json()['text']\n", 85 | "print(transcript)\n", 86 | "\n", 87 | "with open('transcript.txt', 'w') as f:\n", 88 | " f.write(transcript)" 89 | ] 90 | } 91 | ], 92 | "metadata": { 93 | "kernelspec": { 94 | "display_name": "Python 3", 95 | "language": "python", 96 | "name": "python3" 97 | }, 98 | "language_info": { 99 | "codemirror_mode": { 100 | "name": "ipython", 101 | "version": 3 102 | }, 103 | "file_extension": ".py", 104 | "mimetype": "text/x-python", 105 | "name": "python", 106 | "nbconvert_exporter": "python", 107 | "pygments_lexer": "ipython3", 108 | "version": "3.8.8" 109 | }, 110 | "toc": { 111 | "base_numbering": 1, 112 | "nav_menu": {}, 113 | "number_sections": true, 114 | "sideBar": true, 115 | "skip_h1_title": false, 116 | "title_cell": "Table of Contents", 117 | "title_sidebar": "Contents", 118 | "toc_cell": false, 119 | "toc_position": {}, 120 | "toc_section_display": true, 121 | "toc_window_display": false 122 | } 123 | }, 124 | "nbformat": 4, 125 | "nbformat_minor": 5 126 | } 127 | -------------------------------------------------------------------------------- /google-sheets/football_news.csv: -------------------------------------------------------------------------------- 1 | ,title,subtitle,link 2 | 0,CASH & BURN,Biggest net spenders in last ten years revealed with Man Utd top at £904m,https://www.thesun.co.uk/sport/18378142/net-spend-rankings-man-utd-chelsea-barcelona/ 3 | 1,CONT-ING MONEY,Antonio Conte will demand £25m-a-year wages to replace Pochettino at PSG,https://www.thesun.co.uk/sport/18379240/antonio-conte-mauricio-pochettino-tottenham-paris-saint-germain/ 4 | 2,HEN PARTY,Arsenal 'in contact with Osimhen' but Napoli's £84m demands could scupper deal',https://www.thesun.co.uk/sport/football/18378920/arsenal-victor-osimhen-talks-napoli-transfer/ 5 | 3,KEEP SCH-TUM,Scholes spoke to Lingard after letting slip about 'disaster' dressing room,https://www.thesun.co.uk/sport/18378915/man-utd-scholes-lingard-disaster-talks/ 6 | 4,PAR-TNERS,Spurs want No2 to Paratici to help transfer supremo land more key targets,https://www.thesun.co.uk/sport/18377735/tottenham-fabio-paratici-assistant-land-transfer-targets-conte/ 7 | 5,STAT'S MAD,Amazing Man City vs Real stats show how tight Champions League semi will be,https://www.thesun.co.uk/sport/18379690/man-city-real-madrid-champions-league-stats/ 8 | 6,EN GAARD,Odegaard jokes Haaland needs to join Arsenal if he decides to leave Dortmund,https://www.thesun.co.uk/sport/football/18376618/arsenal-martin-odegaard-erling-haaland-transfer/ 9 | 7,MAN RE-UNITED,Ten Hag keen to bring back forgotten Man Utd star who he has known since 13,https://www.thesun.co.uk/sport/18378323/ten-hag-keen-man-united-forgotten-man-return/ 10 | 8,MAD FOR GAB,Arsenal transfer for Jesus 'done and dusted' after talks with representatives,https://www.thesun.co.uk/sport/football/18375212/arsenal-gabriel-jesus-edu-talks-representatives/ 11 | 9,NO MESS-ING,PSG plan to keep Messi for another season 'but open to letting Neymar leave',https://www.thesun.co.uk/sport/18379212/psg-plan-keep-messi-another-season-neymar-axe/ 12 | 10,EUR THE BEST,Ultimate Champions League XI of four semi-final teams including Salah & Torres,https://www.thesun.co.uk/sport/18378156/champions-league-xi-liverpool-city-real-villarreal/ 13 | 11,VICTOR-Y,"Arsenal target Victor Osimhen's tragic story, from losing mum as a child to selling water in the street before stardom",https://www.thesun.co.uk/sport/18375463/arsenal-transfer-target-victor-osimhen-tragic-story/ 14 | 12,ERL-Y DAYS,Haaland posed in Arsenal kit as a kid as Gunners fans joke 'he's coming home',https://www.thesun.co.uk/sport/18371439/erling-haaland-arsenal-kit-transfer-borussia-dortmund/ 15 | 13,ALL WRONG,Sky Sports post brutal video of Allan's shocking Liverpool performance,https://www.thesun.co.uk/sport/18377721/everton-allan-merseyside-derby-liverpool-premier-league/ 16 | 14,KEANE ON HIBS,Roy Keane ready to LEAVE Sky for Hibs as reps make contact with Scottish club,https://www.thesun.co.uk/sport/football/18373857/roy-keane-hibs-manager-sky-sports-man-utd/ 17 | 15,ALISSON BLUNDERLAND,Chelsea refused to pay for Alisson before forking out more for Kepa,https://www.thesun.co.uk/sport/18376097/chelsea-transfer-news-alisson-kepa-liverpool/ 18 | 16,RU CAMP,Man Utd & Arsenal handed Neves blow with Wolves ace ‘crazy about Barcelona’,https://www.thesun.co.uk/sport/18376388/man-utd-arsenal-ruben-neves-transfer-blow-barcelona/ 19 | 17,REAL DREAM TEAM,Who makes our Man City vs Real Madrid combined XI ahead of crunch semi?,https://www.thesun.co.uk/sport/18376667/man-city-real-madrid-combined-xi-champions-league/ 20 | 18,P-RICE-LESS,City OUT of Rice chase as they refuse to fork out £150m after Haaland deal,https://www.thesun.co.uk/sport/football/18373041/man-city-declan-rice-guardiola-west-ham/ 21 | 19,THAT'S YOUR LOTT,Ancelotti opens up on PSG exit & reveals why he asked to QUIT to join Real,https://www.thesun.co.uk/sport/18377421/carlo-ancelotti-quit-psg-real-madrid/ 22 | 20,KOP DROPPED,Liverpool blow as Anfield ruled OUT of hosting any games at Euro 2028,https://www.thesun.co.uk/sport/football/18372736/liverpool-anfield-euro-2028-ineligible/ 23 | 21,IN LUK,Lukaku 'pushing for Inter Milan return but must slash wages in HALF to move',https://www.thesun.co.uk/sport/18374562/chelsea-lukaku-cut-wages-half-inter-milan-transfer/ 24 | 22,GUNNERS NEWS,"Gabriel Jesus 'AGREES' Arsenal move, Gunners 'offered Richarlison transfer',",https://www.thesun.co.uk/sport/18346781/arsenal-news-live-gabriel-jesus-transfer-richarlison-cristiano-ronaldo/ 25 | 23,BLUES NEWS,"Chelsea 'in Antony talks', Fofana 'wanted to replace Rudiger'",https://www.thesun.co.uk/sport/18346702/chelsea-news-live-antony-transfer-fofana-rudiger-takeover/ 26 | 24,MAN UTD NEWS,"Ten Hag's 'De Gea concerns' revealed, Paul Pogba 'leaves club WhatsApp group'",https://www.thesun.co.uk/sport/18174940/man-utd-news-live-de-gea-ten-hag-pogba-transfer/ 27 | 25,APPY EVER AFTER,Pogba 'leaves Man Utd WhatsApp group and tells team-mates he's off',https://www.thesun.co.uk/sport/football/18370041/paul-pogba-man-utd-whatsapp/ 28 | 26,BIG BUCKS,Chelsea rebel Rudiger set to bank almost £60MILLION with mega Real Madrid move,https://www.thesun.co.uk/sport/18373365/antonio-rudiger-60million-transfer-real-madrid-chelsea/ 29 | 27,PALACE 0 LEEDS 0,Visitors earn vital point at Selhurst Park in bid to beat relegation,https://www.thesun.co.uk/sport/18372216/crystal-palace-0-leeds-0-match-report/ 30 | 28,SAK ATTACK,Arsenal fans go wild after clip of Bukayo Saka 'bullying' Man Utd's Alex Telles,https://www.thesun.co.uk/sport/18378641/arsenal-bukayo-saka-manchester-united-alex-telles/ 31 | 29,EK CHASE,Man Utd and Chelsea in Hugo Ekitike chase with Reims ready to sell star for £30m,https://www.thesun.co.uk/sport/18375311/man-utd-chelsea-reims-hugo-ekitike-transfer/ 32 | 30,GAMES OF THRONE,"City ready to dethrone Euro kings and finally become top dogs, says Silva",https://www.thesun.co.uk/sport/18372792/man-city-real-madrid-champions-league-bernardo-silva/ 33 | 31,ANITA'S NEAT FINISH,Aston Villa ace and former England centre-back Asante to retire,https://www.thesun.co.uk/sport/18378844/anita-asante-to-retire-villa/ 34 | 32,KYLER BLOW,Real Madrid transfer blow after Mbappe holds ‘positive’ contract talks with PSG,https://www.thesun.co.uk/sport/18375750/kylian-mbappe-holds-positive-talks-psg/ 35 | 33,ART GALLERY,How Arsenal could start next term if Arteta lands Gabriel Jesus and Ruben Neves,https://www.thesun.co.uk/sport/football/18377217/arsenal-line-up-next-season-jesus-neves/ 36 | 34,LONG BALL GAME,Chelsea bidders told they're not allowed to sell club for at least TEN YEARS,https://www.thesun.co.uk/sport/18366994/chelsea-roman-abramovich-boehly-broughton-pagliuca/ 37 | 35,HALL ABOUT THAT,West Ham flop is top transfer target to replace Robert Lewandowski,https://www.thesun.co.uk/sport/18376792/west-ham-flop-bayern-transfer-replacement-lewandowski/ 38 | 36,TEE TIME,John Terry enjoys round of golf with Tottenham stars Harry Kane and Eric Dier,https://www.thesun.co.uk/sport/football/18371794/chelsea-terry-tottenham-kane-dier/ 39 | 37,HELLS BELS,West Ham ‘to fight Arsenal in free transfer race for Italy ace Andrea Belotti',https://www.thesun.co.uk/sport/football/18375864/west-ham-arsenal-transfer-andrea-belotti/ 40 | 38,HUGH BEAUTY,Watch Man Utd icon & Bradford boss Hughes show off stunning skills at 58,https://www.thesun.co.uk/sport/18365393/man-utd-legend-bradford-hughes-skills/ 41 | 39,TOP TABLE,How Luton boss Jones got them to verge of Prem.. by BURNING a table tennis table,https://www.thesun.co.uk/sport/18377157/luton-town-nathan-jones-success-championship-play-offs/ 42 | 40,CARRA RINSED,Neville rips into Carragher's 'yellow rinse' hair & compares him to presenter,https://www.thesun.co.uk/sport/football/18373149/gary-neville-jamie-carragher-bullseye/ 43 | 41,LEARNER DIVER,Furious fan dragged by police after invading pitch to show keeper how to DIVE,https://www.thesun.co.uk/sport/18365439/fan-riot-police-pitch-invader-goalkeeper/ 44 | 42,DEAL WITH IT,Sterling puts Man City contract talks on hold after failing to reach new terms,https://www.thesun.co.uk/sport/football/18370704/raheem-sterling-man-city-contract-talks/ 45 | 43,PIERS PLEA,Morgan begs Ronaldo to quit Utd for Arsenal as team-mates ‘don’t respect him’,https://www.thesun.co.uk/sport/18368251/piers-morgan-cristiano-ronaldo-quit-man-utd-arsenal-transfer/ 46 | 44,GARY'S PAIN,"I was plagued by tiny coffin nightmare as son battled leukaemia, says Lineker",https://www.thesun.co.uk/sport/18371220/gary-lineker-nightmares-son-george-cancer/ 47 | 45,CIAO PABLO,Arsenal star Pablo Mari wanted by Udinese permanently after impressive loan,https://www.thesun.co.uk/sport/18374650/arsenal-pablo-mari-udinese-permanent-transfer/ 48 | 46,TEENAGE KICKS,"Watch Southampton youngster Dibling, 16, score hat-trick of identical goals",https://www.thesun.co.uk/sport/18377622/southampton-dibling-hat-trick-identical-goals-newcastle/ 49 | 47,RED WORRIES,Utd stars ‘fear Ten Hag doesn’t have strong enough personality to handle squad’,https://www.thesun.co.uk/sport/18374529/man-utd-players-erik-ten-hag-personality-fears/ 50 | 48,TOO COQSURE,Coquelin slams Bayern's 'arrogant attitude' & plots another upset vs Liverpool,https://www.thesun.co.uk/sport/18377806/francis-coquelin-bayern-arrogant-attitude-liverpool/ 51 | 49,DEVILS DESPAIR,Maguire leads FOUR Man Utd flops in list of players with MOST Prem blunders,https://www.thesun.co.uk/sport/18360574/harry-maguire-man-utd-premier-league-blunders-stats/ 52 | 50,SPURRED ON,How Spurs could line up under Pochettino with Kane to STAY & return for Eriksen,https://www.thesun.co.uk/sport/18365604/tottenham-line-up-pochettino-kane-eriksen-phillips-marquinhos/ 53 | --------------------------------------------------------------------------------