Python Beautiful Soup find_all

3

你好,我正在尝试从一个网站获取一些信息。如果我格式化有任何错误,请原谅,这是我第一次发帖到SO。

soup.find('div', {"class":"stars"}) 

我从这里获得:

<div class="stars" title="4.0 star rating">
<i class="star star--large star-0"></i><i class="star star--large star- 
1"></i><i class="star star--large star-2"></i><i class="star star--large 
star-3"></i><i class="star star--large star-4 star--large--muted"></i> 
</div>

我需要那个"4.0星评等"

当我使用:

soup.find('div', {"class":"stars"})["title"]

它可以工作,但对于find_all不适用。但我正在尝试找到所有情况并将它们放入列表中。

以下是我的完整代码。

    def get_info():
        from IPython.display import HTML
        import requests
        from bs4 import BeautifulSoup
        n = 1
        for page in range(53):
            url = f"https://www.sitejabber.com/reviews/apple.com?page= 
   {n}&sort=Reviews.processed&direction=DESC#reviews"
            r = requests.get(url)
            soup = BeautifulSoup(r.text, 'lxml')
            all_reviews = soup.find_all('div', {'class':"truncate_review"})
            all_dates = soup.find_all('div', {'class':'review__date'},'title')
            all_titles = soup.find_all('span', {'class':'review__title__text'})
            reviews_class = soup.find('div', {"class":"review__stars"})
            for review in all_reviews:

    all_reviews_list.append(review.text.replace("\n","").replace("\t",""))
            for date in all_dates:

all_dates_list.append(date.text.replace("\n","").replace("\t",""))
            for title in all_titles:

  all_titles_list.append(title.text.replace("\n","").replace("\t",""))
            for stars in reviews_class.find_all('div', {'class':'stars'}):
                all_star_ratings.append(stars['title'])



            n += 1

抱歉,我的缩进有点乱,但这是我完整的代码。


当您使用rang()时,需要另一个变量n吗? - Joshua Varghese
@JoshuaVarghese 我使用n来更改页面编号,当它在f-string中循环时,但我想我可以从1开始范围,并将页面放入f-string中。感谢您指出这一点。 - JGW
2个回答

0

像在字典中一样遍历bs4元素。
如果您正在使用find()

soup.find('div', {"class":"stars"}) ['title']

这个方法可行,因为find()返回单个值。
但是如果你使用find_all(),它会返回一个列表,而list[string]是无效的处理方式。
因此,你可以创建一个包含这些值的列表:

res = []
for i in soup.find_all('div', {"class":"stars"}):
    res.append(i['title'])

否则,作为一行代码:

res = [i['title'] for i in soup.find_all('div', {"class":"stars"})]

由于您想要获取所有评论的标题,您需要指定评论容器,也就是从抓取

<div class="review__container">

那么代码将会是:

review = soup.find_all('div',class_="review__container")
res = [i['title'] for j in review for i in j.find_all('div',class_='stars')]

给出:

['1.0 star rating', '1.0 star rating', '3.0 star rating', '1.0 star rating', '1.0 star rating', '1.0 star rating', '1.0 star rating', '1.0 star rating', '1.0 star rating', '1.0 star rating', '5.0 star rating', '1.0 star rating', '1.0 star rating', '1.0 star rating', '1.0 star rating', '1.0 star rating', '1.0 star rating', '5.0 star rating', '2.0 star rating', '5.0 star rating', '1.0 star rating', '2.0 star rating', '1.0 star rating', '5.0 star rating', '1.0 star rating', '5.0 star rating']

嗨,Joshua,也许我应该发布我的所有代码。我先找到另一个类并将其存储在变量中,然后再查找。否则,我会在评论之前考虑星级评分。我尝试了你说的方法,但似乎在列表中一遍又一遍地返回相同的答案。reviews_class = soup.find('div',{"class":"review__stars"})for stars in reviews_class.find_all('div',{'class':'stars'}): all_star_ratings.append(stars ['title'])这给了我1颗星,1颗星,1颗星...... - JGW
我的问题是这是一个评论网站。我关注的是评论。在页面早些时候,有商店和其他方面的星级评分。我只需要与评论本身相关的星级评分,而不是页面顶部的综合评分。只是为了澄清一下。 - JGW

0
以下怎么样?
from bs4 import BeautifulSoup

html = """<div class="stars" title="4.0 star rating">
<i class="star star--large star-0"></i><i class="star star--large star- 
1"></i><i class="star star--large star-2"></i><i class="star star--large 
star-3"></i><i class="star star--large star-4 star--large--muted"></i> 
</div>"""

soup = BeautifulSoup(html, features="lxml")
element = soup.select('.stars')[0]['title']
print(element)

打印

4.0 star rating

使用URL
import requests
from bs4 import BeautifulSoup

url = 'https://www.sitejabber.com/reviews/apple.com?page={n}&sort=Reviews.processed&direction=DESC#reviews'
page = requests.get(url=url)

soup = BeautifulSoup(page.text, features="lxml")

elements = soup.select('.stars')
# print(elements)

for element in elements:
    print(element['title'])

打印

4.0 star rating
3.8 star rating
3.7 star rating
4.3 star rating
3.8 star rating
4.2 star rating
0.0 star rating
0.0 star rating
5.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
3.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
5.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
1.0 star rating
5.0 star rating
2.0 star rating
5.0 star rating
1.0 star rating
2.0 star rating
1.0 star rating
5.0 star rating
1.0 star rating
5.0 star rating
4.3 star rating
3.5 star rating
4.7 star rating
3.7 star rating
4.8 star rating
3.7 star rating

这确实很好用,但我需要跳过前几个星级评分,并确保它们从评论部分开始显示。其次,我需要它适用于所有实例并存储在列表中。谢谢您的帮助。 - JGW
有没有办法从HTML的特定部分开始?我的问题是这是一个评论网站。我专注于评论。在页面的早期,有商店和其他方面的星级评分。我只需要与评论本身相关的星级评分,而不是页面顶部的综合评分。 - JGW
@JGW 确定要从 review__flex 开始吗? - 0m3r

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接