【问题标题】:Beautiful soup for web scraping returns none网页抓取的美丽汤没有回报
【发布时间】:2018-06-19 12:11:53
【问题描述】:
import requests
from bs4 import BeautifulSoup
#Finds the imdb rating of a given movie or TV series
search_term1="What is the imdb rating of "
search_term2=input("Enter the name of the movie or TV Series : ")
search_term=search_term1+search_term2
response=requests.get("https://www.google.co.in/search?q="+search_term)

soup = BeautifulSoup(response.text, 'html5lib')
match=soup.find('div.slp.f')
#i tried 'div',_class="slp.f"
print(match) #this line is returning none

我正在尝试从谷歌搜索引擎中提取电影的 imdb 评级。每次它都没有返回,尽管 id 是正确的。

【问题讨论】:

  • 这是因为您的脚本会引导您进入验证码页面。尝试使用print(response.url) 进行检查。我猜返回的url和请求的url不一样。
  • 此外,您的搜索词应正确编码,我在您的脚本中看不到任何此类尝试。如果您请求的网址尚未重定向,请尝试使用quote_plus(search_term) 和之前的from urllib.parse import quote_plus

标签: html web-scraping beautifulsoup python-requests web-crawler


【解决方案1】:

如果你尝试在 DOM 中找到before-appbar

import requests
from bs4 import BeautifulSoup
#Finds the imdb rating of a given movie or TV series
search_term1="What is the imdb rating of "
search_term2=input("Enter the name of the movie or TV Series : ")
search_term=search_term1+search_term2
response=requests.get("https://www.google.co.in/search?q="+search_term)
print("before-appbar" in response.text)

输出是False

很明显,“before-appbar”在这里不是任何元素的 Id。

我的猜测是您正试图通过从浏览器中检查 DOM 元素来确定它。然而在大多数情况下,DOM 被 JS 改变了很多,所以它与你在 python 中使用requests 得到的不匹配。

我可以建议您两种可能的解决方案:

  1. 将响应保存在 html 文件中,在浏览器中打开,然后 检查您需要找到的元素。

    f = open("response.html", "w")
    f.write(response.text)
    f.close()
    
  2. 使用selenium 和无头浏览器。

【讨论】:

    【解决方案2】:

    问题取决于您尝试搜索 id 而不是

    print(soup.find(id="before-appbar")) print(soup.find({"id":"before-appbar"}))

    希望这能解决问题。

    【讨论】:

      【解决方案3】:

      您将find() 视为select() method that accepts CSS selectorsfind() 方法 接受 CSS 选择器语法。

      find('div.slp.f')    # No
      find('div', 'slp f') # will work with find(). Syntax: ('tag', 'class') or ('tag', class_='class')
      select('div.slp.f')  # Yes
      

      尝试使用lxml 而不是html5lib,因为html5lib is the slowest。此外,在selenium 中也不需要将响应保存在文件中,因为此类任务提到的Bishakh Ghosh

      如果不使用selenium,请确保您使用的是user-agent,否则Google 最终会阻止请求,因为requests 库中的默认user-agentpython-requests,并且Google 知道它是机器人而不是“真正的”用户访问,并会阻止请求。


      由于您没有提到您尝试从页面的哪个部分抓取数据(有机结果、知识图或答案框),所以我不会费心寻找合适的元素出现在每个搜索结果中,因此评分将始终存在。

      代码:

      from bs4 import BeautifulSoup
      import requests, lxml
      
      headers = {
          'User-agent':
          "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
      }
      
      params = {
        "q": "imdb rating of infinity war",
        "hl": "en"
      }
      
      html = requests.get("https://www.google.com/search", headers=headers, params=params)
      soup = BeautifulSoup(html.text, 'lxml')
      
      # scrapes from the snippet organic result
      rating = soup.select_one('g-review-stars+ span').text
      print(rating)
      
      # Rating: 8.4/10
      

      或者,您可以使用来自 SerpApi 的 Google Organic Results API 来实现相同的目的。这是一个带有免费计划的付费 API。

      您的情况的不同之处在于迭代结构化 JSON 字符串并获取您想要的数据,而不是弄清楚为什么某些事情不工作或按应有的方式提取。

      要集成的代码:

      from serpapi import GoogleSearch
      
      params = {
        "api_key": "YOUR_API_KEY",
        "engine": "google",
        "q": "what is imdb rating of infinity war",
        "gl": "us",
        "hl": "en"
      }
      
      search = GoogleSearch(params)
      results = search.get_dict()
      
      rating = results['organic_results'][0]['rich_snippet']['top']['detected_extensions']['rating']
      print(rating)
      
      # 8.4
      

      免责声明,我为 SerpApi 工作。

      【讨论】:

        猜你喜欢
        • 2021-03-30
        • 1970-01-01
        • 2019-05-05
        • 1970-01-01
        • 1970-01-01
        • 2021-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多