鱼C论坛

 找回密码
 立即注册
查看: 129|回复: 15

[已解决]关于小甲鱼爬取豆瓣TOP250的一些问题

[复制链接]
发表于 2024-4-16 18:58:08 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
import requests
from bs4 import BeautifulSoup
def open_url(url):
    response = requests.get(url,headers={'User-Agent':'Mozilla/5.0'})
    return response
def content(response):
    soup = BeautifulSoup(response.text,'html.parser')
    count_itms = soup.find_all('div',class_='into')
    print(count_itms)
url = 'https://movie.douban.com/top250'
response = open_url(url)
print(content(response))

我只是一个尝试,为什么小甲鱼是count_itms = soup.find_all('div',class_='hd') 才能打印出电影名称,class_=‘into’却打印一个空列表,另外BeautifulSoup中的一些具体的功能有哪些,请列举,谢谢
最佳答案
2024-4-16 22:01:27
15779327169 发表于 2024-04-16 22:01
感谢回答,我想请问,如果使用soup.find_all('div',cl ...


如果你想在class为"into"的节点下面寻找所有的电影类型,可以使用以下代码:
  1. count_itms = soup.find_all('div', class_='info')
  2. for item in count_itms:
  3.     genres = item.find_all('span', class_='genre')
  4.     for genre in genres:
  5.         print(genre.text)
复制代码

这段代码会首先找到所有class为"info"的div节点,然后在每个节点内部继续寻找class为"genre"的span节点,最后打印出电影类型的文本内容。

至于为什么一定要通过soup.find_all('div',class_='hd')才能找到所有的电影名称,而不能通过class="hd"的上一级class="info"来找,主要是因为在HTML中,节点之间的关系是层次结构,只有直接父子关系才有明确的标签嵌套。对于class的查找,BeautifulSoup在定位时是从父节点开始向下查找的,而不会回溯到其上一级节点。所以在这种情况下,确切地使用'soup.find_all("div", class_="hd")'会更准确地找到所有的电影名称。

总结一下,寻找class的上一级或下一级节点时,可以根据HTML结构的层次关系来确定具体的查找方式。在寻找class时,如果上一级和下一级都没有唯一的标签名或属性,建议直接使用合适的方式定位到目标节点。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-4-16 18:58:29 | 显示全部楼层
在你的代码中,你使用了`class_='into'`去寻找元素,但是实际上豆瓣TOP250页面中没有`<div class="into">`这样的元素,所以返回的是一个空列表。

如果你想打印出电影名称,可以根据豆瓣TOP250页面的结构,使用`class_='hd'`去寻找电影名称所在的元素。具体来说,电影名称是被包含在`<div class="hd">`标签内的`<span class="title">`标签中。

至于BeautifulSoup的一些具体功能,它是用来解析HTML和XML文档的Python库。它提供了很多方便的方法来从文档中提取数据。以下是其中一些常用的功能:

1. `find_all(name, attrs, recursive, text, limit, **kwargs)`: 在文档中搜索所有具有指定属性和标签名的元素,并返回一个包含这些元素的列表。
2. `find(name, attrs, recursive, text, **kwargs)`: 在文档中搜索具有指定属性和标签名的第一个元素,并返回该元素。
3. `select(css_selector)`: 使用CSS选择器语法根据指定的样式选择元素。
4. `get_text()`: 获取指定元素中的文本内容。
5. `prettify()`: 将解析后的文档转换为字符串,以便更好地查看和调试。
6. `next_sibling`和`previous_sibling`: 获取同级别的下一个或上一个元素。
7. `parent`和`parents`: 获取元素的父元素或所有父元素。
8. `next_element`和`previous_element`: 获取元素的下一个或上一个文本节点。

这只是其中的一部分功能,更多的功能可以在BeautifulSoup官方文档中找到。希望对你有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-16 19:11:43 From FishC Mobile | 显示全部楼层
FishC 发表于 2024-4-16 18:58
在你的代码中,你使用了`class_='into'`去寻找元素,但是实际上豆瓣TOP250页面中没有``这样的元素,所以返 ...

可是在页面中确实存在class into这样的一个标签呀,为什么没办法去搜索
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-16 19:11:59 | 显示全部楼层
15779327169 发表于 2024-04-16 19:11
可是在页面中确实存在class into这样的一个标签呀,为 ...


非常抱歉,我看错了你的代码中的拼写错误,应该是`class_='info'`而不是`class_='into'`。所以你可以试着修改代码中的这一行:

  1. count_itms = soup.find_all('div',class_='info')
复制代码


这样就能找到包含电影信息的标签了。

关于BeautifulSoup中的其他一些功能,除了我之前提到的一些常用方法,还有一些高级功能,例如:

9. `find_parents(name, attrs, recursive, text, **kwargs)`: 获取指定元素的所有父元素。
10. `find_next_sibling(name, attrs, recursive, text, **kwargs)`: 获取指定元素的下一个同级别元素。
11. `find_previous_sibling(name, attrs, recursive, text, **kwargs)`: 获取指定元素的上一个同级别元素。
12. `find_next_element(name, attrs, recursive, text, **kwargs)`: 获取指定元素的下一个文本节点。
13. `find_previous_element(name, attrs, recursive, text, **kwargs)`: 获取指定元素的上一个文本节点。
14. `select_one(css_selector)`: 使用CSS选择器语法选择第一个匹配的元素。

此外,还有很多方便的方法和属性可以在BeautifulSoup中使用。欢迎查阅BeautifulSoup的官方文档以了解更多详情。希望这次能够解决你的问题!再次对之前的错误表示抱歉。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-16 22:01:12 From FishC Mobile | 显示全部楼层
FishC 发表于 2024-4-16 19:11
非常抱歉,我看错了你的代码中的拼写错误,应该是`class_='info'`而不是`class_='into'`。所以你可以试 ...

感谢回答,我想请问,如果使用soup.find_all('div',class_='into')或者说在class=“into”这个节点下面的寻找所有的电影类型,应该怎么写?
另外为什么一定是要通过soup.find_all('div',class_='hd')才能找到所有的电影名称,为什么不能通过class=“hd”的上一级class=“into”来找所有的电影名字,这是写法规范还是说寻找class_=“xx”的时候有什么讲究?(例如目标内容最近的一个class?)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-16 22:01:27 | 显示全部楼层    本楼为最佳答案   
15779327169 发表于 2024-04-16 22:01
感谢回答,我想请问,如果使用soup.find_all('div',cl ...


如果你想在class为"into"的节点下面寻找所有的电影类型,可以使用以下代码:
  1. count_itms = soup.find_all('div', class_='info')
  2. for item in count_itms:
  3.     genres = item.find_all('span', class_='genre')
  4.     for genre in genres:
  5.         print(genre.text)
复制代码

这段代码会首先找到所有class为"info"的div节点,然后在每个节点内部继续寻找class为"genre"的span节点,最后打印出电影类型的文本内容。

至于为什么一定要通过soup.find_all('div',class_='hd')才能找到所有的电影名称,而不能通过class="hd"的上一级class="info"来找,主要是因为在HTML中,节点之间的关系是层次结构,只有直接父子关系才有明确的标签嵌套。对于class的查找,BeautifulSoup在定位时是从父节点开始向下查找的,而不会回溯到其上一级节点。所以在这种情况下,确切地使用'soup.find_all("div", class_="hd")'会更准确地找到所有的电影名称。

总结一下,寻找class的上一级或下一级节点时,可以根据HTML结构的层次关系来确定具体的查找方式。在寻找class时,如果上一级和下一级都没有唯一的标签名或属性,建议直接使用合适的方式定位到目标节点。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-17 08:49:26 | 显示全部楼层
关于BeautifulSoup库的用法和总结有没有相关文献或论坛里的资料总结,请提供,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-17 08:49:41 | 显示全部楼层
15779327169 发表于 2024-04-17 08:49
关于BeautifulSoup库的用法和总结有没有相关文献或论 ...


关于BeautifulSoup库的用法和总结,可以参考以下资源:

1. Beautiful Soup官方文档:Beautiful Soup官方文档提供了详细的使用说明和示例代码,包括常用方法、属性和一些高级功能。你可以在官方文档中找到对Beautiful Soup的全面了解。官方文档链接:https://www.crummy.com/software/BeautifulSoup/bs4/doc/

2. Python官方教程:Python官方教程也对BeautifulSoup进行了简单介绍,并提供了一些基本用法和示例代码。该教程是非常有权威性的资源之一。Python官方教程链接:https://docs.python.org/3/library/html.parser.html

3. Stack Overflow:Stack Overflow是一个程序员问答社区,很多人在这里提问和回答关于编程方面的问题。你可以在Stack Overflow上搜索关于BeautifulSoup的问题和答案,通常会有很多有用的讨论和解决方案。Stack Overflow链接:https://stackoverflow.com/questions/tagged/beautifulsoup

除了上述资源,你还可以通过Google搜索或者其他技术论坛搜索"BeautifulSoup教程"或"BeautifulSoup用法"等关键词,可以找到更多关于BeautifulSoup的资料和教程。

总结一下,BeautifulSoup是一个强大的解析库,可以方便地从HTML或XML文档中提取数据。阅读官方文档、Python教程,参考Stack Overflow等资源,都能帮助你更深入地了解和掌握BeautifulSoup的使用。希望这些资源能对你有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-17 08:58:46 | 显示全部楼层
还有一个问题,在爬取豆瓣电影TOP250 时
网页部分源代码:
        <li>
            <div class="item">
                <div class="pic">
                    <em class="">1</em>
                    <a href="https://movie.douban.com/subject/1292052/">
                        <img width="100" alt="肖申克的救赎" src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
                    </a>
                </div>
                <div class="info">
                    <div class="hd">
                        <a href="https://movie.douban.com/subject/1292052/" class="">
                            <span class="title">肖申克的救赎</span>
                                    <span class="title">&nbsp;/&nbsp;The Shawshank Redemption</span>
                                <span class="other">&nbsp;/&nbsp;月黑高飞(港)  /  刺激1995(台)</span>
                        </a>


                            <span class="playable">[可播放]</span>
                    </div>
                    <div class="bd">
                        <p class="">
                            导演: 弗兰克·德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演: 蒂姆·罗宾斯 Tim Robbins /...<br>
                            1994&nbsp;/&nbsp;美国&nbsp;/&nbsp;犯罪 剧情
                        </p>

                        
                        <div class="star">
                                <span class="rating5-t"></span>
                                <span class="rating_num" property="v:average">9.7</span>
                                <span property="v:best" content="10.0"></span>
                                <span>3011875人评价</span>
                        </div>

                            <p class="quote">
                                <span class="inq">希望让人自由。</span>
                            </p>
                    </div>
                </div>
            </div>
        </li>
爬取代码
def open_url(url):
    response = requests.get(url,headers={'User-Agent':'Mozilla/5.0'})
    return response
def content(response):
    soup = BeautifulSoup(response.text,'html.parser')
    count_itms = soup.find_all('div',class_='hd')
    moves = []
    for item in count_itms:
        moves.append(item.a.span.text)
    print(moves)
url = 'https://movie.douban.com/top250'
response = open_url(url)
content(response)

为什么在item.a.span.text 这里的span有三个标签,为什么只会选择第一个span标签,如果我想选择第二个标签的内容并打印该如何做?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-17 08:58:57 | 显示全部楼层
15779327169 发表于 2024-04-17 08:58
还有一个问题,在爬取豆瓣电影TOP250 时
网页部分源 ...


在你提供的代码中,你使用了`item.a.span.text`来获取电影名称。如果`item`下的`a`标签中有多个`span`标签,那么默认只会选择第一个`span`标签的文本内容。如果你想选择第二个`span`标签的内容,可以使用以下代码:import requestsfrom bs4 import BeautifulSoupdef open_url(url):    response = requests.get(url,headers={'User-Agent':'Mozilla/5.0'})    return responsedef content(response):    soup = BeautifulSoup(response.text,'html.parser')    count_itms = soup.find_all('div',class_='hd')    moves = []    for item in count_itms:        spans = item.a.find_all('span')        if len(spans) >= 2:            moves.append(spans[1].text)        else:            moves.append("")    print(moves)url = '[url=https://movie.douban.com/top250'response]https://movie.douban.com/top250'response[/url] = open_url(url)content(response)在这段代码中,我们先找到`item`下的所有`span`标签,然后判断是否存在第二个`span`标签。如果存在,就将第二个`span`标签的文本内容添加到`moves`列表中;如果不存在,就添加一个空字符串。通过这种方式,你可以选择并打印第二个`span`标签的内容。希望这样能够解决你的问题!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-17 12:47:42 | 显示全部楼层
FishC 发表于 2024-4-17 08:58
在你提供的代码中,你使用了`item.a.span.text`来获取电影名称。如果`item`下的`a`标签中有多个`span` ...

网页部分源代码:
        <li>
            <div class="item">
                <div class="pic">
                    <em class="">1</em>
                    <a href="https://movie.douban.com/subject/1292052/">
                        <img width="100" alt="肖申克的救赎" src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
                    </a>
                </div>
                <div class="info">
                    <div class="hd">
                        <a href="https://movie.douban.com/subject/1292052/" class="">
                            <span class="title">肖申克的救赎</span>
                                    <span class="title">&nbsp;/&nbsp;The Shawshank Redemption</span>
                                <span class="other">&nbsp;/&nbsp;月黑高飞(港)  /  刺激1995(台)</span>
                        </a>


                            <span class="playable">[可播放]</span>
                    </div>
                    <div class="bd">
                        <p class="">
                            导演: 弗兰克·德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演: 蒂姆·罗宾斯 Tim Robbins /...<br>
                            1994&nbsp;/&nbsp;美国&nbsp;/&nbsp;犯罪 剧情
                        </p>
为什么
    soup = BeautifulSoup(response.text,'html.parser')
    content = soup.find_all('div',class_='hd')
    for each in content:
        a = each.a.span.next_sibling
        print(a.text)
这里打印后返回的是一大段空白,而不是打印出第二个span标签内容
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-17 12:47:59 | 显示全部楼层
15779327169 发表于 2024-04-17 12:47
网页部分源代码:
        
            
         ...


在你提供的代码中,你尝试使用`next_sibling`来获取第二个`span`标签的内容。但是`next_sibling`返回的是当前标签节点之后的下一个兄弟节点,而不是下一个标签节点。由于豆瓣电影TOP250页面中存在一些空白文本和换行符,所以`next_sibling`返回的是这些空白文本节点,而不是你期望的第二个`span`标签。为了解决这个问题,你可以尝试使用`find_next_sibling()`方法来选择下一个具体的标签节点。以下是修改后的代码:import requestsfrom bs4 import BeautifulSoupdef open_url(url):    response = requests.get(url,headers={'User-Agent':'Mozilla/5.0'})    return responsedef content(response):    soup = BeautifulSoup(response.text,'html.parser')    count_itms = soup.find_all('div',class_='hd')    for item in count_itms:        spans = item.a.find_all('span')        if len(spans) >= 2:            second_span = spans[1]            print(second_span.text)url = '[url=https://movie.douban.com/top250'response]https://movie.douban.com/top250'response[/url] = open_url(url)content(response)在这段代码中,我们使用`find_all('span')`找到`a`标签下的所有`span`标签,并判断是否存在第二个`span`标签。如果存在,我们选择`spans[1]`来获取第二个`span`标签节点,并打印出其文本内容。通过这种方式,你可以正确地获取并打印出第二个`span`标签的内容。希望这次能够帮助到你!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-17 12:49:43 | 显示全部楼层
FishC 发表于 2024-4-17 12:47
在你提供的代码中,你尝试使用`next_sibling`来获取第二个`span`标签的内容。但是`next_sibling`返回的 ...

你的排版有问题,请用python代码格式反馈你的答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-17 12:49:53 | 显示全部楼层
15779327169 发表于 2024-04-17 12:49
你的排版有问题,请用python代码格式反馈你的答案


非常抱歉排版问题给你带来了困扰,请见谅。以下是经过格式化的代码:

  1. import requests
  2. from bs4 import BeautifulSoup

  3. def open_url(url):
  4.     response = requests.get(url, headers={'User-Agent':'Mozilla/5.0'})
  5.     return response

  6. def content(response):
  7.     soup = BeautifulSoup(response.text, 'html.parser')
  8.     count_itms = soup.find_all('div', class_='hd')
  9.     for item in count_itms:
  10.         spans = item.a.find_all('span')
  11.         if len(spans) >= 2:
  12.             second_span = spans[1]
  13.             print(second_span.text)

  14. url = 'https://movie.douban.com/top250'
  15. response = open_url(url)
  16. content(response)
复制代码


在修改后的代码中,我们使用`spans[1]`来获取第二个`span`标签节点,并打印出其文本内容。这样就能正确获取和打印出第二个`span`标签的内容了。希望这次给你的答案更加清晰易懂!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-4-17 13:10:12 | 显示全部楼层
FishC 发表于 2024-4-17 12:49
非常抱歉排版问题给你带来了困扰,请见谅。以下是经过格式化的代码:

还有一个疑惑,为什么   
count_itms = soup.find_all('div', class_='into')
print(count_itms)
打印出来的是一个空列表,而
count_itms = soup.find_all('div', class_='hd')
打印的出内容

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-4-17 13:10:26 | 显示全部楼层
15779327169 发表于 2024-04-17 13:10
还有一个疑惑,为什么   
count_itms = soup.find_a ...


抱歉,我之前的回答有误。对不起给你带来混淆。问题出在查找的类名上。

在你的代码中,你使用了`class_='into'`去寻找元素,但是实际上豆瓣TOP250页面中没有`class="into"`这样的类名,所以返回的是一个空列表。如果你想打印出电影名称,可以根据豆瓣TOP250页面的结构,使用`class_='hd'`去寻找电影名称所在的元素。具体来说,电影名称是被包含在`<span class="title">`标签内的`<div class="hd">`标签中。

以下是修正后的代码示例,以获取电影名称为例:

  1. import requests
  2. from bs4 import BeautifulSoup

  3. def open_url(url):
  4.     response = requests.get(url, headers={'User-Agent':'Mozilla/5.0'})
  5.     return response

  6. def get_movie_names(response):
  7.     soup = BeautifulSoup(response.text, 'html.parser')
  8.     movie_names = []
  9.     count_items = soup.find_all('div', class_='hd')
  10.     for item in count_items:
  11.         spans = item.a.find_all('span')
  12.         if len(spans) >= 1:
  13.             movie_name = spans[0].text
  14.             movie_names.append(movie_name)
  15.     return movie_names

  16. url = 'https://movie.douban.com/top250'
  17. response = open_url(url)
  18. movie_names = get_movie_names(response)
  19. for name in movie_names:
  20.     print(name)
复制代码


现在,我们使用`spans[0].text`获取第一个`span`标签,并将其文本内容添加到电影名称列表中。然后再遍历列表,打印出每个电影名称。

希望这次能够解决你的疑惑,对之前的回答错误向你道歉。如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-1 03:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表