mirror of
https://github.com/OpenVoiceOS/OpenVoiceOS
synced 2025-02-13 10:20:38 +01:00
Add youtube-search to the rootfs overlay
Todo: create buildroot packages
This commit is contained in:
parent
d889128a9e
commit
11159f2bef
@ -0,0 +1 @@
|
|||||||
|
pip
|
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 joe tats
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
@ -0,0 +1,44 @@
|
|||||||
|
Metadata-Version: 2.1
|
||||||
|
Name: youtube-search
|
||||||
|
Version: 2.1.2
|
||||||
|
Summary: Perform YouTube video searches without the API
|
||||||
|
Home-page: https://github.com/joetats/youtube_search
|
||||||
|
Author: Joe Tatusko
|
||||||
|
Author-email: tatuskojc@gmail.com
|
||||||
|
License: MIT
|
||||||
|
Classifier: License :: OSI Approved :: MIT License
|
||||||
|
Classifier: Programming Language :: Python :: 3
|
||||||
|
Classifier: Programming Language :: Python :: 3.7
|
||||||
|
Classifier: Programming Language :: Python :: 3.8
|
||||||
|
Description-Content-Type: text/markdown
|
||||||
|
License-File: LICENSE
|
||||||
|
Requires-Dist: requests
|
||||||
|
|
||||||
|
# youtube_search
|
||||||
|
|
||||||
|
Python function for searching for youtube videos to avoid using their heavily rate-limited API
|
||||||
|
|
||||||
|
To avoid using the API, this uses the form on the youtube homepage and scrapes the resulting page.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
For a basic search (and all of the current functionality), you can use the search tool as follows:
|
||||||
|
|
||||||
|
```pip install youtube-search```
|
||||||
|
|
||||||
|
```python
|
||||||
|
from youtube_search import YoutubeSearch
|
||||||
|
|
||||||
|
results = YoutubeSearch('search terms', max_results=10).to_json()
|
||||||
|
|
||||||
|
print(results)
|
||||||
|
|
||||||
|
# returns a json string
|
||||||
|
|
||||||
|
########################################
|
||||||
|
|
||||||
|
results = YoutubeSearch('search terms', max_results=10).to_dict()
|
||||||
|
|
||||||
|
print(results)
|
||||||
|
# returns a dictionary
|
||||||
|
```
|
@ -0,0 +1,9 @@
|
|||||||
|
youtube_search-2.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||||
|
youtube_search-2.1.2.dist-info/LICENSE,sha256=zVjZaKVVhb_CGuoJOu5bqSpnhbqyTJlpz-LNi_6eqD0,1065
|
||||||
|
youtube_search-2.1.2.dist-info/METADATA,sha256=wEWvppkKB-B7DeOSj2BSxXRurMUpNdWkteSIopw51Xo,1197
|
||||||
|
youtube_search-2.1.2.dist-info/RECORD,,
|
||||||
|
youtube_search-2.1.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||||
|
youtube_search-2.1.2.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
||||||
|
youtube_search-2.1.2.dist-info/top_level.txt,sha256=a9m0vWREPPFPH9ghqteiTbDyIOTXrXickQ3rb4SZtRQ,15
|
||||||
|
youtube_search/__init__.py,sha256=DoUp4KBhq9WeNp531X1zfVTYkF5WZ6BzG_fbxQRehHc,2834
|
||||||
|
youtube_search/__init__.pyc,,
|
@ -0,0 +1,5 @@
|
|||||||
|
Wheel-Version: 1.0
|
||||||
|
Generator: bdist_wheel (0.37.1)
|
||||||
|
Root-Is-Purelib: true
|
||||||
|
Tag: py3-none-any
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
youtube_search
|
@ -0,0 +1,65 @@
|
|||||||
|
import requests
|
||||||
|
import urllib.parse
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class YoutubeSearch:
|
||||||
|
def __init__(self, search_terms: str, max_results=None):
|
||||||
|
self.search_terms = search_terms
|
||||||
|
self.max_results = max_results
|
||||||
|
self.videos = self._search()
|
||||||
|
|
||||||
|
def _search(self):
|
||||||
|
encoded_search = urllib.parse.quote_plus(self.search_terms)
|
||||||
|
BASE_URL = "https://youtube.com"
|
||||||
|
url = f"{BASE_URL}/results?search_query={encoded_search}"
|
||||||
|
response = requests.get(url).text
|
||||||
|
while "ytInitialData" not in response:
|
||||||
|
response = requests.get(url).text
|
||||||
|
results = self._parse_html(response)
|
||||||
|
if self.max_results is not None and len(results) > self.max_results:
|
||||||
|
return results[: self.max_results]
|
||||||
|
return results
|
||||||
|
|
||||||
|
def _parse_html(self, response):
|
||||||
|
results = []
|
||||||
|
start = (
|
||||||
|
response.index("ytInitialData")
|
||||||
|
+ len("ytInitialData")
|
||||||
|
+ 3
|
||||||
|
)
|
||||||
|
end = response.index("};", start) + 1
|
||||||
|
json_str = response[start:end]
|
||||||
|
data = json.loads(json_str)
|
||||||
|
|
||||||
|
for contents in data["contents"]["twoColumnSearchResultsRenderer"]["primaryContents"]["sectionListRenderer"]["contents"]:
|
||||||
|
for video in contents["itemSectionRenderer"]["contents"]:
|
||||||
|
res = {}
|
||||||
|
if "videoRenderer" in video.keys():
|
||||||
|
video_data = video.get("videoRenderer", {})
|
||||||
|
res["id"] = video_data.get("videoId", None)
|
||||||
|
res["thumbnails"] = [thumb.get("url", None) for thumb in video_data.get("thumbnail", {}).get("thumbnails", [{}]) ]
|
||||||
|
res["title"] = video_data.get("title", {}).get("runs", [[{}]])[0].get("text", None)
|
||||||
|
res["long_desc"] = video_data.get("descriptionSnippet", {}).get("runs", [{}])[0].get("text", None)
|
||||||
|
res["channel"] = video_data.get("longBylineText", {}).get("runs", [[{}]])[0].get("text", None)
|
||||||
|
res["duration"] = video_data.get("lengthText", {}).get("simpleText", 0)
|
||||||
|
res["views"] = video_data.get("viewCountText", {}).get("simpleText", 0)
|
||||||
|
res["publish_time"] = video_data.get("publishedTimeText", {}).get("simpleText", 0)
|
||||||
|
res["url_suffix"] = video_data.get("navigationEndpoint", {}).get("commandMetadata", {}).get("webCommandMetadata", {}).get("url", None)
|
||||||
|
results.append(res)
|
||||||
|
|
||||||
|
if results:
|
||||||
|
return results
|
||||||
|
return results
|
||||||
|
|
||||||
|
def to_dict(self, clear_cache=True):
|
||||||
|
result = self.videos
|
||||||
|
if clear_cache:
|
||||||
|
self.videos = ""
|
||||||
|
return result
|
||||||
|
|
||||||
|
def to_json(self, clear_cache=True):
|
||||||
|
result = json.dumps({"videos": self.videos})
|
||||||
|
if clear_cache:
|
||||||
|
self.videos = ""
|
||||||
|
return result
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user