![](/img/trans.png)
[英]How to scrape star ratings using Selenium or Beautifulsoup in Python?
[英]How can I scrape yelp reviews and star ratings into CSV using Python beautifulsoup
我一直在嘗試使用 Python 抓取 Yelp 評論和評分,但我走到了死胡同。
我能夠使用for
循環獲取干凈的 Yelp 評論列表並將其附加到列表中,但是當我嘗試相同的評分時,我一直只獲得第一個評分。 這是我嘗試過的:
for i in range(0,10):
url = "YELP LINK GOES HERE"
ourUrl = urllib.request.urlopen(url)
soup = BeautifulSoup(ourUrl,'html.parser')
review = soup.find_all('p',{'class':'comment__373c0'})
for i in range(0,len(review)):
rating = soup.find("div",{"class":"i-stars__373c0"}).get('aria-label')
print(rating)
輸出:
3 star rating
soup.find("div",{"class":"i-stars__373c0___sZu0"}).get('aria-label')
輸出:
'3 star rating'
print(soup.select('[aria-label*=rating]')[0]['aria-label'])
輸出:
3 star rating
soup.find_all('div',{'class':'i-stars__373c0___sZu0'})
這里的輸出為我提供了代碼中的每個星級評分,但如下所示:
aria-label="3 star rating" class="i-stars__373c0___sZu0
aria-label="3 star rating" class="i-stars__373c0___sZu0
aria-label="1 star rating" class="i-stars__373c0___sZu0
aria-label="2.5 star rating" class="i-stars__373c0___sZu0
# ... etc
我的預期輸出是:
1. Review: text here
Rating: x star rating
我正在使用 Jupyter Notebook。
Yelp 是 JavaScript 驅動的。 每個頁面都有一個 JSON 負載,其中包含腳本標簽中的評論,但在 JS 運行並動態注入之前頁面上沒有評論。 如果您在瀏覽器中訪問 URL 或查看其頁面源之前禁用 JS,您將在對urllib.request.urlopen(url)
調用的響應中看到您必須使用的靜態 HTML。
這是我們想要的數據,為清楚起見省略了:
<script type="application/ld+json">{"@context":"https://schema.org","@type":"Restaurant","name":"Code Red Restaurant & Lounge" ... [more JSON] ...}</script>
使用 Python的規范線程Web-scraping JavaScript 頁面中的此答案中描述了訪問此數據的一種方法。 策略是從<script>
標簽中解析 JSON(或 JS 對象)數據。 在這種情況下,它是格式良好的 JSON,因此您可以使用json.loads
來創建字典而無需任何預處理:
import json
import requests
from bs4 import BeautifulSoup
url = "https://www.yelp.com/biz/code-red-restaurant-and-lounge-bronx-2?osq=code+red"
res = requests.get(url)
res.raise_for_status()
soup = BeautifulSoup(res.text, "lxml")
jsons = (
json.loads(x.contents[0])
for x in soup.select('script[type="application/ld+json"]')
)
restaurant_data = next(
x for x in jsons if "@type" in x and x["@type"] == "Restaurant"
)
print(json.dumps(restaurant_data, indent=2))
restaurant_data
字典具有以下結構:
$ py scrape_yelp_reviews.py | jq 'keys'
[
"@context",
"@type",
"address",
"aggregateRating",
"image",
"name",
"priceRange",
"review",
"servesCuisine",
"telephone"
]
"review"
是評論列表,每條評論都有您感興趣的評分和描述:
$ py scrape_yelp_reviews.py | jq '.review[0] | keys'
[
"author",
"datePublished",
"description",
"reviewRating"
]
評論看起來像:
{
"author": "Nova R.",
"datePublished": "2021-04-04",
"reviewRating": {
"ratingValue": 1
},
"description": "Once upon a time , ... [rest of review text] ... "
}
如果您想獲取所有評論,您可以使用start=n
查詢參數以 10 為增量遍歷頁面:
import itertools
import json
import requests
from bs4 import BeautifulSoup
all_reviews = []
for start in itertools.count(0, 10):
url = ("https://www.yelp.com/biz/code-red-restaurant-"
"and-lounge-bronx-2?osq=code+red&start=%s") % start
res = requests.get(url)
if not res.ok:
break
soup = BeautifulSoup(res.text, "lxml")
jsons = (
json.loads(x.contents[0])
for x in soup.select('script[type="application/ld+json"]')
)
try:
restaurant_data = next(
x for x in jsons if "@type" in x and x["@type"] == "Restaurant"
)
except StopIteration:
break
all_reviews.extend(restaurant_data["review"])
print(json.dumps(all_reviews, indent=2))
print(len(all_reviews))
如果您想加快速度,您可以使用 asyncio 或線程,如Python 從頁面上的鏈接下載多個文件 中所述。
不用說,但如果 Yelp 更改其 JSON 格式,代碼就會中斷。 另一個可能更可靠的選擇是使用像Pyppeteer或Selenium這樣的實時抓取工具(但是如果 CSS 選擇器發生變化,事情就會中斷,所以選擇你的毒葯)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.