AttributeError: у объекта 'NoneType' нет атрибута 'find_all' Beautifulsoup - PullRequest
0 голосов
/ 08 мая 2019

Я пытаюсь вычеркнуть цену дома по этой ссылке: 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 ]

2 голосов
/ 08 мая 2019

Вы пытаетесь найти что-то, чего не существует в данных, возвращаемых 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.

Так что в основном вынеобходимо убедиться, что у вас есть правильные данные, прежде чем начать их обработку.Вы можете получить данные без блокировки, используя Selenium и ChromeDriver , как подсказывает KunduK в своем ответе.Вы можете получить ChromeDriver от http://chromedriver.chromium.org/

2 голосов
/ 08 мая 2019

Блокировка и использование селена уже были рассмотрены.Я покажу способ получить все списки в хорошем формате JSON, где вы можете легко извлечь информацию.Если вы используете selenium для перехода на каждую страницу, вы можете использовать regex для извлечения всей информации о списках на странице и передачи в json.loads для создания объекта json, пример здесь , вы можете легко проанализировать всю информациюза листинг

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)

Regex объяснение:

image

Попробуйте здесь

2 голосов
/ 08 мая 2019

Здесь JavaScripts рендерит на страницу. Вы можете использовать и селен, и красивый суп, чтобы получить желаемый результат.

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...