本文教你使用 requests_html 和 Beautiful Soup 库在 Python 中抓取 YouTube 视频并提取有用的视频信息,例如标题、总观看次数、发布日期、视频时长、标签、喜欢和不喜欢等。
网络抓取是从网站中提取数据。它是一种复制形式,其中收集特定数据并将其从网络复制到中央本地数据库或电子表格中,以供以后分析或检索。
Python如何提取YouTube数据?由于YouTube是互联网上最大的视频共享网站,从中提取数据非常有用,你可以找到最受欢迎的频道、跟踪频道的受欢迎程度、记录视频的喜欢、不喜欢和观看次数等等。在本教程中,你将学习如何在 Python 中使用requests_html和BeautifulSoup从 YouTube 视频中提取数据。
请注意,使用此方法提取 YouTube 数据是不可靠的,因为 YouTube 不断更改其代码,该代码在任何时候都无法运行。因此,为了更可靠的使用,我建议你改用 YouTube API 来提取数据。
相关: 如何在 Python 中提取 YouTube 评论。
Python提取YouTube数据示例介绍和解析 - 安装所需的依赖项:
pip3 install requests_html bs4
如何在Python中提取YouTube数据?在我们深入研究快速脚本之前,我们需要试验如何使用BeautifulSoup从网站中提取此类数据,打开 Python 交互式 shell 并编写以下代码行:
from requests_html import HTMLSession
from bs4 import BeautifulSoup as bs # importing BeautifulSoup
# sample youtube video url
video_url = "https://www.youtube.com/watch?v=jNQXAC9IVRw"
# init an HTML Session
session = HTMLSession()
# get the html content
response = session.get(video_url)
# execute Java-script
response.html.render(sleep=1)
# create bs object to parse HTML
soup = bs(response.html.html, "html.parser")
这会向该 YouTube 视频 URL 发出请求,呈现 Javascript 并最终创建包装生成的 HTML 的 BeatifulSoup 对象。
太好了,现在让我们尝试查找页面中的所有元标记:
In [10]: soup.find_all("meta")
Out[10]:
[<meta content="IE=edge" http-equiv="X-UA-Compatible"/>,
<meta content="rgba(255,255,255,0.98)" name="theme-color"/>,
<meta content="Me at the zoo" name="title"/>,
<meta content="The first video on YouTube. While you wait for Part 2, listen to this great song: https://www.youtube.com/watch?v=zj82_v2R6ts" name="description"/>,
<meta content="me at the zoo, jawed karim, first youtube video" name="keywords"/>,
<meta content="YouTube" property="og:site_name"/>,
<meta content="https://www.youtube.com/watch?v=jNQXAC9IVRw" property="og:url"/>,
<meta content="Me at the zoo" property="og:title"/>,
<meta content="https://i.ytimg.com/vi/jNQXAC9IVRw/hqdefault.jpg" property="og:image"/>,
<meta content="480" property="og:image:width"/>,
<meta content="360" property="og:image:height"/>,
<meta content="The first video on YouTube. While you wait for Part 2, listen to this great song: https://www.youtube.com/watch?v=zj82_v2R6ts" property="og:description"/>,
<meta content="544007664" property="al:ios:app_store_id"/>,
<meta content="YouTube" property="al:ios:app_name"/>,
<meta content="vnd.youtube://www.youtube.com/watch?v=jNQXAC9IVRw&feature=applinks" property="al:ios:url"/>,
<meta content="vnd.youtube://www.youtube.com/watch?v=jNQXAC9IVRw&feature=applinks" property="al:android:url"/>,
<meta content="http://www.youtube.com/watch?v=jNQXAC9IVRw&feature=applinks" property="al:web:url"/>,
<meta content="video.other" property="og:type"/>,
<meta content="https://www.youtube.com/embed/jNQXAC9IVRw" property="og:video:url"/>,
<meta content="https://www.youtube.com/embed/jNQXAC9IVRw" property="og:video:secure_url"/>,
<meta content="text/html" property="og:video:type"/>,
<meta content="480" property="og:video:width"/>,
<meta content="360" property="og:video:height"/>,
<meta content="YouTube" property="al:android:app_name"/>,
<meta content="com.google.android.youtube" property="al:android:package"/>,
<meta content="me at the zoo" property="og:video:tag"/>,
<meta content="jawed karim" property="og:video:tag"/>,
<meta content="first youtube video" property="og:video:tag"/>,
<meta content="87741124305" property="fb:app_id"/>,
<meta content="player" name="twitter:card"/>,
<meta content="@youtube" name="twitter:site"/>,
<meta content="https://www.youtube.com/watch?v=jNQXAC9IVRw" name="twitter:url"/>,
<meta content="Me at the zoo" name="twitter:title"/>,
<meta content="The first video on YouTube. While you wait for Part 2, listen to this great song: https://www.youtube.com/watch?v=zj82_v2R6ts" name="twitter:description"/>,
<meta content="https://i.ytimg.com/vi/jNQXAC9IVRw/hqdefault.jpg" name="twitter:image"/>,
<meta content="YouTube" name="twitter:app:name:iphone"/>,
<meta content="544007664" name="twitter:app:id:iphone"/>,
<meta content="YouTube" name="twitter:app:name:ipad"/>,
<meta content="544007664" name="twitter:app:id:ipad"/>,
<meta content="vnd.youtube://www.youtube.com/watch?v=jNQXAC9IVRw&feature=applinks" name="twitter:app:url:iphone"/>,
<meta content="vnd.youtube://www.youtube.com/watch?v=jNQXAC9IVRw&feature=applinks" name="twitter:app:url:ipad"/>,
<meta content="YouTube" name="twitter:app:name:googleplay"/>,
<meta content="com.google.android.youtube" name="twitter:app:id:googleplay"/>,
<meta content="https://www.youtube.com/watch?v=jNQXAC9IVRw" name="twitter:app:url:googleplay"/>,
<meta content="https://www.youtube.com/embed/jNQXAC9IVRw" name="twitter:player"/>,
<meta content="480" name="twitter:player:width"/>,
<meta content="360" name="twitter:player:height"/>,
<meta content="Me at the zoo" itemprop="name"/>,
<meta content="The first video on YouTube. While you wait for Part 2, listen to this great song: https://www.youtube.com/watch?v=zj82_v2R6ts" itemprop="description"/>,
<meta content="False" itemprop="paid"/>,
<meta content="UC4QobU6STFB0P71PMvOGN5A" itemprop="channelId"/>,
<meta content="jNQXAC9IVRw" itemprop="videoId"/>,
<meta content="PT0M19S" itemprop="duration"/>,
<meta content="False" itemprop="unlisted"/>,
<meta content="480" itemprop="width"/>,
<meta content="360" itemprop="height"/>,
<meta content="HTML5 Flash" itemprop="playerType"/>,
<meta content="480" itemprop="width"/>,
<meta content="360" itemprop="height"/>,
<meta content="true" itemprop="isFamilyFriendly"/>,
<meta content="AD,AE,AF,AG,AI,AL,AM,AO,AQ,AR,AS,AT,AU,AW,AX,AZ,BA,BB,BD,BE,BF,BG,BH,BI,BJ,BL,BM,BN,BO,BQ,BR,BS,BT,BV,BW,BY,BZ,CA,CC,CD,CF,CG,CH,CI,CK,CL,CM,CN,CO,CR,CU,CV,CW,CX,CY,CZ,DE,DJ,DK,DM,DO,DZ,EC,EE,EG,EH,ER,ES,ET,FI,FJ,FK,FM,FO,FR,GA,GB,GD,GE,GF,GG,GH,GI,GL,GM,GN,GP,GQ,GR,GS,GT,GU,GW,GY,HK,HM,HN,HR,HT,HU,ID,IE,IL,IM,IN,IO,IQ,IR,IS,IT,JE,JM,JO,JP,KE,KG,KH,KI,KM,KN,KP,KR,KW,KY,KZ,LA,LB,LC,LI,LK,LR,LS,LT,LU,LV,LY,MA,MC,MD,ME,MF,MG,MH,MK,ML,MM,MN,MO,MP,MQ,MR,MS,MT,MU,MV,MW,MX,MY,MZ,NA,NC,NE,NF,NG,NI,NL,NO,NP,NR,NU,NZ,OM,PA,PE,PF,PG,PH,PK,PL,PM,PN,PR,PS,PT,PW,PY,QA,RE,RO,RS,RU,RW,SA,SB,SC,SD,SE,SG,SH,SI,SJ,SK,SL,SM,SN,SO,SR,SS,ST,SV,SX,SY,SZ,TC,TD,TF,TG,TH,TJ,TK,TL,TM,TN,TO,TR,TT,TV,TW,TZ,UA,UG,UM,US,UY,UZ,VA,VC,VE,VG,VI,VN,VU,WF,WS,YE,YT,ZA,ZM,ZW" itemprop="regionsAllowed"/>,
<meta content="172826227" itemprop="interactionCount"/>,
<meta content="2005-04-23" itemprop="datePublished"/>,
<meta content="2005-04-23" itemprop="uploadDate"/>,
<meta content="Film & Animation" itemprop="genre"/>]
就这么简单,这里有很多有用的数据。例如,我们可以通过以下方式获取视频标题:
In [11]: soup.find("meta", itemprop="name")["content"]
Out[11]: 'Me at the zoo'
或观看次数:
In [12]: soup.find("meta", itemprop="interactionCount")['content']
Out[12]: '172826227'
这样,你将能够从该网页中提取你想要的所有内容。现在让我们制作我们的脚本,从 YouTube 视频页面中提取一些有用的信息,打开一个新的 Python 文件并继续操作:
导入必要的模块:
from requests_html import HTMLSession
from bs4 import BeautifulSoup as bs
在我们制作提取所有视频数据的函数之前,让我们初始化我们的 HTTP 会话:
# init session
session = HTMLSession()
Python如何提取YouTube数据?让我们创建一个函数,给定一个 YouTube 视频的 URL,它将返回字典中的所有数据:
def get_video_info(url):
# download HTML code
response = session.get(url)
# execute Javascript
response.html.render(sleep=1)
# create beautiful soup object to parse HTML
soup = bs(response.html.html, "html.parser")
# open("index.html", "w").write(response.html.html)
# initialize the result
result = {}
请注意,在我们下载网页的 HTML 内容后,我们运行render()
了执行 Javascript 的方法,以便我们正在查找的数据在 HTML 中呈现。
请注意,如果你收到超时错误,那么你可以简单地添加timeout
参数并将其设置为 60 秒(默认为 8 秒)或其他内容,如下所示:
response.html.render(sleep=1, timeout=60)
检索视频标题:
# video title
result["title"] = soup.find("meta", itemprop="name")['content']
转换为整数的视图数:
# video views (converted to integer)
result["views"] = result["views"] = soup.find("meta", itemprop="interactionCount")['content']
获取视频说明:
# video description
result["description"] = soup.find("meta", itemprop="description")['content']
视频发布日期:
# date published
result["date_published"] = soup.find("meta", itemprop="datePublished")['content']
视频时长:
# get the duration of the video
result["duration"] = soup.find("span", {"class": "ytp-time-duration"}).text
Python提取YouTube数据示例:我们可以从元标记中获取持续时间作为以前的字段,但它将采用另一种格式,例如PT0M19S
转换为 19 秒或00:19
采用ytp-time-duration
span
标记中的格式。
我们还可以提取视频标签:
# get the video tags
result["tags"] = ', '.join([ meta.attrs.get("content") for meta in soup.find_all("meta", {"property": "og:video:tag"}) ])
喜欢和不喜欢的数量作为整数:
# number of likes
text_yt_formatted_strings = soup.find_all("yt-formatted-string", {"id": "text", "class": "ytd-toggle-button-renderer"})
result["likes"] = ''.join([ c for c in text_yt_formatted_strings[0].attrs.get("aria-label") if c.isdigit() ])
result["likes"] = 0 if result['likes'] == '' else int(result['likes'])
# number of dislikes
result["dislikes"] = ''.join([ c for c in text_yt_formatted_strings[1].attrs.get("aria-label") if c.isdigit() ])
result['dislikes'] = 0 if result['dislikes'] == '' else int(result['dislikes'])
如何在Python中提取YouTube数据?由于在 YouTube 视频中,你可以看到频道详细信息,例如名称和订阅者数量,让我们也抓取它:
# channel details
channel_tag = soup.find("yt-formatted-string", {"class": "ytd-channel-name"}).find("a")
# channel name
channel_name = channel_tag.text
# channel URL
channel_url = f"https://www.youtube.com{channel_tag['href']}"
# number of subscribers as str
channel_subscribers = soup.find("yt-formatted-string", {"id": "owner-sub-count"}).text.strip()
result['channel'] = {'name': channel_name, 'url': channel_url, 'subscribers': channel_subscribers}
return result
由于soup.find()函数返回一个Tag对象,你仍然可以在其他标签中找到HTML 标签。因此,多次调用find()是一种常见的做法。
现在这个函数在字典中返回了很多视频信息,让我们完成我们的脚本:
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="YouTube Video Data Extractor")
parser.add_argument("url", help="URL of the YouTube video")
args = parser.parse_args()
url = args.url
# get the data
data = get_video_info(url)
# print in nice format
print(f"Title: {data['title']}")
print(f"Views: {data['views']}")
print(f"Published at: {data['date_published']}")
print(f"Video Duration: {data['duration']}")
print(f"Video tags: {data['tags']}")
print(f"Likes: {data['likes']}")
print(f"Dislikes: {data['dislikes']}")
print(f"\nDescription: {data['description']}\n")
print(f"\nChannel Name: {data['channel']['name']}")
print(f"Channel URL: {data['channel']['url']}")
print(f"Channel Subscribers: {data['channel']['subscribers']}")
Python提取YouTube数据示例:复制这里没什么特别的,因为我们需要一种从命令行检索视频 URL 的方法,上面就是这样做的,然后以某种格式打印出来,这是我运行脚本时的输出:
C:\youtube-extractor>python extract_video_info.py https://www.youtube.com/watch?v=jNQXAC9IVRw
Title: Me at the zoo
Views: 172639597
Published at: 2005-04-23
Video Duration: 0:18
Video tags: me at the zoo, jawed karim, first youtube video
Likes: 8188077
Dislikes: 191986
Description: The first video on YouTube. While you wait for Part 2, listen to this great song: https://www.youtube.com/watch?v=zj82_v2R6ts
Channel Name: jawed
Channel URL: https://www.youtube.com/channel/UC4QobU6STFB0P71PMvOGN5A
Channel Subscribers: 1.98M subscribers
结论
Python如何提取YouTube数据?学完这个教程后你知道如何从 HTML 标签中提取数据,然后继续添加其他字段,例如视频质量等。
现在如果你想提取 YouTube 评论,除此之外还有很多事情要做,有一个单独的教程。
你不仅可以提取 YouTube 视频详细信息,还可以将此技能应用于你想要的任何网站。如果你想提取维基百科页面,有一个教程!或者你想从 Google 抓取天气数据?也有一个教程。
在此处查看本教程的完整代码。
注意: YouTube 会不断更改视频页面的 HTML 结构。如果本教程的代码不适合你,请改用 YouTube API 教程查看 。