AttributeError:'NoneType'对象没有属性'find_all'Beautifulsoup

时间:2019-05-08 13:59:35

标签: python html web web-scraping beautifulsoup

我正在尝试通过以下链接获取房屋价格:https://www.leboncoin.fr/ventes_immobilieres/offres/ile_de_france/p-2/

我需要知道我的程序有什么问题吗?

我的程序:

import csv
import requests
from bs4 import BeautifulSoup

with open("bc.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["prix", "code_postal", "description", "nombre_pieces", "surface"]) 
    for i in range(1, 20):
        url = "https://www.leboncoin.fr/ventes_immobilieres/offres/ile_de_france/p-%s/" % i
        soup = BeautifulSoup(requests.get(url).text, "html.parser")
        repo = soup.find(class_="undefined")
        for repo in repo.find_all("li", attrs={"itemscope itemtype": "http://schema.org/Offer"}):
            prix = repo.find("span", {"itemprop": "priceCurrency"})
            prix = prix.text if prix else ""
            writer.writerow([prix])

我收到此错误:

Traceback (most recent call last):
File "nv.py", line 14, in <module>
for repo in repo.find_all("li", attrs={"itemscope itemtype": "http://schema.org/Offer"}):
AttributeError: 'NoneType' object has no attribute 'find_all'

3 个答案:

答案 0 :(得分:2)

这里的JavaScript呈现到页面上。您可以同时使用硒和漂亮的汤来获得所需的输出。

from selenium import webdriver
from bs4 import BeautifulSoup
driver=webdriver.Chrome('path of the chrome driver')
driver.get("https://www.leboncoin.fr/ventes_immobilieres/offres/ile_de_france/p-2/")
soup=BeautifulSoup(driver.page_source,'html.parser')
repo = soup.find(class_="undefined")
for repo in repo.find_all("li", attrs={"itemtype": "http://schema.org/Offer"}):
    prix = repo.find("span", {"itemprop": "priceCurrency"})
    if prix.text!='':
       print(prix.text)

答案 1 :(得分:2)

您正在尝试搜索requests返回的数据中不存在的内容。

当您选中requests.get(url).text时,您可能会看到类似以下内容的内容:

<!--
Need permission to access data? Contact: DataAccess@datadome.co
-->
<html><head><title>You have been blocked</title><style>#cmsg{animation: A 1.5s;}@keyframes A{0%{opacity:0;}99%{opacity:0;}100%{opacity:1;}}</style></head><body style="margin:0"><p id="cmsg">Please enable JS and disable any ad blocker</p><script>var dd={'cid':'AHrlqAAAAAMAptz12-9nkWQAJcs_Yg==','hsh':'05B30BD9055986BD2EE8F5A199D973','t':'fe'}</script><script src="https://ct.datadome.co/c.js"></script></body></html>

导致None被分配给变量repo的结果,解释器抱怨类型find_all()的对象不存在属性None

因此,基本上,您需要在开始处理数据之前确保拥有正确的数据。正如 KunduK 在他的回答中所建议的那样,您可以使用 Selenium ChromeDriver 来获取数据而不会被阻塞。您可以从http://chromedriver.chromium.org/

获取 ChromeDriver

答案 2 :(得分:2)

已经涵盖了硒的阻断和使用。我将展示一种以不错的json格式获取所有列表的方法,您可以在其中轻松提取信息。如果使用硒进入每个页面,则可以使用正则表达式提取页面上的所有列表信息,并传递给json.loads生成json对象example here,您可以轻松地解析每个列表的所有信息< / p>

from selenium import webdriver
import re
import json

p = re.compile(r'({"req.*).*[^\r\n]')
driver = webdriver.Chrome()
driver.get("https://www.leboncoin.fr/ventes_immobilieres/offres/ile_de_france/p-3/")
soup = bs(driver.page_source,'html.parser')
data = json.loads(p.findall(driver.page_source)[0])
listings = data['data']['ads']

for listing in listings:
    print(listing)

正则表达式说明:

尝试here