网页抓取中的问题

时间:2020-03-22 14:04:57

标签: python html web-scraping

我正在尝试使用 PyCharm 编写程序(我以前没有使用过此IDE,但我不认为这是问题所在)从某个 类, “ react-contextmenu-wrapper”

收集数据时遇到麻烦

我想编写一个脚本来解析Spotify上的网页并使用数据创建一个CSV文件,我一直在关注YouTube上的教程,但我一定在某个地方出错了。

这是我的代码:

from urllib.request import urlopen as Req
from bs4 import BeautifulSoup as soup

my_url = "https://open.spotify.com/genre/NMF-PopularNewReleases"

#grabs the contense of the page
Client = Req(my_url)

#reads the contense of the page
html = Client.read()

#outputs the page
Client.close()

page = soup(html, "html.parser")

#grabs each playlist
playlists = page.findAll("div",{"class":"react-contextmenu-wrapper"})

print(len(playlists))

但是终端输出一个空列表,我知道该类存在。检查页面元素时可以查看它。

1 个答案:

答案 0 :(得分:5)

该元素的类名为react-contextmenu-wrapper的事实是一个很大的提示。 React是一个用于创建用户界面的JavaScript库。

可以使用多种方法来填充网页元素。如果幸运的话,服务器将向您发送.html,其中所有内容基本上都已包含在内-使用BeautifulSoup进行刮擦和解析很简单。

但是,许多现代网站都使用JavaScript动态填充网页元素。当您在浏览器中查看这样的页面时,这没问题-但是,如果您尝试抓取这样的页面,您最终只会得到“裸露的骨头”模板.html,而DOM却没有被完全填充。这就是BeautifulSoup无法看到此元素的原因。

重点是:仅仅因为您可以在浏览器中看到某个元素,并不意味着BeautifulSoup就能看到它。

每当您要抓取网页时,我认为您的首选武器不应是BeautifulSoup-您应将BeautifulSoup作为最后的手段。您应该始终做的第一件事就是检查您要抓取的页面是否向API发出了任何请求,API的响应用于填充自身。如果是这样,您可以简单地将请求模拟到相同的API,并获取所有可能要抓取的内容。好像还不够好,这些API通常会提供JSON,而解析起来很简单。

这是您的操作方式:

  1. 在浏览器中打开网页。
  2. 如果您使用的是Google Chrome浏览器,请按F12键以访问 开发人员工具(其他现代浏览器应具有类似的功能 功能。)
  3. 打开“网络”标签。我们将使用Chrome的网络记录器进行记录 该网页提出的所有请求。
  4. 单击漏斗形图标(激活后变为红色)以 启用过滤。
  5. 单击XHR(这意味着仅查看XMLHttpRequests。这些是 我们感兴趣的一种请求,因为我们希望看到 对API的潜在传出请求-我们不希望捕获对图像等资源的请求。)
  6. Ctrl + E或单击左上角的圆形记录按钮 启用日志记录(激活后,该记录也会变为红色。)
  7. Ctrl + R刷新页面并开始记录流量。
  8. 您应该看到随着页面加载后请求列表的增长 令人耳目一新。看起来像这样(对不起, 图片):
  9. 就我而言,Spotify在发布过程中提出了9个XHR请求(在左侧) 我记录流量的时间。我点击了其中一些 检查了他们的“标头”标签,直到我发现其中的“标头” 似乎与API通讯的网址”(“ api”是 这种情况下的网址。)

该用requests编写一个简单的脚本了。您将要复制 “请求网址”,并确保复制一些“请求标头” 看起来它们对于请求也可能很重要:

import requests

url = "https://api.spotify.com/v1/views/NMF-PopularNewReleases?timestamp=2020-03-22T14%3A26%3A36.760Z&platform=web&content_limit=10&limit=20&types=album%2Cplaylist%2Cartist%2Cshow%2Cstation&image_style=gradient_overlay&country=us&market=us&locale=en"

headers = {
    "Authorization": "Bearer BQDJeAA33JWAC_pQVUxoPpama63RFFIsovMjNOjq_odaPx9EfyMz1Bo494Xv4a20H9gM7Hu0OYZrO3QWs2E"
}

response = requests.get(url, headers=headers)
response.raise_for_status()

data = response.json()

for item in data["content"]["items"]:
    print(item["name"])

运行此脚本时,得到以下输出:

New Music Friday
After Hours
Colores
kelsea
Actions
Kid Krow
Walk Em Down (feat. Roddy Ricch)
Studio It’s Hits
Intentions (Acoustic)
Creep
Is Everybody Going Crazy?
2 Seater (feat. G-Eazy & Offset)
Roses/Lotus/Violet/Iris
Spotify Singles
Between Us (feat. Snoh Aalegra)
E.P.
Black Men Don’t Cheat (feat. Ari Lennox, 6LACK & Tink)
Think About You
Pray 4 Love
Acrobats
>>> 

可以随意检查API返回的JSON对象-您可以在Python中执行此操作,也可以通过从Chrome开发者工具中的“标题”标签切换到“预览”标签来查看JSON的内容。在我的示例中,我只是在首页提取了歌曲的标题,但是JSON对象包含了很多有趣的东西。您还可以在URL的查询字符串中使用参数来获取20首以上的歌曲,等等。