Python Webscraping: как il oop много URL-запросов? - PullRequest
0 голосов
/ 13 апреля 2020
import requests
from bs4 import BeautifulSoup
LURL="https://www.erkunde-die-welt.de/laender-hauptstaedte-welt/"
Lpage = requests.get(LURL)
Lsoup = BeautifulSoup(Lpage.content, 'html.parser')
Lx = Lsoup.find_all(class_="column-2")
a=[]
for Lx in Lx:
  a.append(Lx.text)
a.remove("Land")
j=0
for i in range(len(a)):
  b = a[j]
  URL = "https://de.wikipedia.org/wiki/"+b
  page = requests.get(URL)
  soup = BeautifulSoup(page.content, 'html.parser')
  l = soup.find(class_="firstHeading")
  zr = soup.find(class_="wikitable infobox infoboxstaat float-right")
  z = zr.findAll("tr")
  a=""
  for z in z:
    a=a+z.text
  h=a.find("Hauptstadt")
  lol=a[h:-1]
  lol=lol.replace("Hauptstadt", "")
  lol=lol.strip()
  fg=lol.find("\n")
  lol=lol[0:fg]
  lol=lol.strip()
  j=j+1
  print(lol)
  print(l.text)

Это код. Он получает название каждой страны и упаковывает его в список. После этого программа просматривает страницы стран википедии, получает столицу страны и печатает ее. Это прекрасно работает для каждой страны. Но после завершения одной страны и повторного запуска кода она перестает работать с ошибкой:

Traceback (most recent call last):   File "main.py", line 19, in <module>
    z = zr.findAll("tr") AttributeError: 'NoneType' object has no attribute 'findAll'

Ответы [ 3 ]

1 голос
/ 14 апреля 2020

Вы сохранили список стран в переменной с именем a, которую затем переписали в сценарии с другим значением. Это портит вашу итерацию. Два хороших способа предотвращения подобных проблем:

  1. Используйте более значимые имена переменных.
  2. Используйте mypy в своем коде Python.

Я потратил немного времени, пытаясь выполнить базовую c очистку вашего кода, чтобы хотя бы избавить вас от этой первой ошибки; список стран теперь называется countries вместо a, что не позволяет вам перезаписать его, и я заменил крайне запутанную итерацию i/j/a/b на очень простую for country in countries l oop. Я также избавился от всех переменных, которые использовались только один раз, поэтому мне не пришлось бы пытаться придумать для них лучшие имена. Я думаю, что предстоит еще проделать большую работу, но мне не хватает представления о том, что делает этот внутренний l oop, чтобы хотеть даже попытаться это исправить. Удачи!

import requests
from bs4 import BeautifulSoup

countries = [x.text for x in BeautifulSoup(
    requests.get(
        "https://www.erkunde-die-welt.de/laender-hauptstaedte-welt/"
    ).content,
    'html.parser'
).find_all(class_="column-2")]
countries.remove("Land")

for country in countries:
    soup = BeautifulSoup(
        requests.get(
            "https://de.wikipedia.org/wiki/" + country
        ).content,
        'html.parser'
    )
    heading = soup.find(class_="firstHeading")
    rows = soup.find(
        class_="wikitable infobox infoboxstaat float-right"
    ).findAll("tr")
    a = ""
    for row in rows:
        a += row.text
        h = a.find("Hauptstadt")
        lol = a[h:-1]
        lol = lol.replace("Hauptstadt", "")
        lol = lol.strip()
        fg = lol.find("\n")
        lol = lol[0:fg]
        lol = lol.strip()
        print(lol)
        print(heading.text)
1 голос
/ 13 апреля 2020

Сообщение об ошибке на самом деле говорит вам, что происходит. Строка кода

z = zr.findAll("tr")

выдает ошибку атрибута, поскольку объект NoneType не имеет атрибута findAll. Вы пытаетесь вызвать findAll для zr, предполагая, что переменная всегда будет объектом BeautifulSoup, но не будет. Если эта строка:

zr = soup.find(class_="wikitable infobox infoboxstaat float-right")

не найдет объектов в html, соответствующих этим классам, для zr будет установлено значение None. Итак, на одной из страниц, которые вы пытаетесь очистить, вот что происходит. Вы можете закодировать его с помощью оператора try / исключением, например:

for i in range(len(a)):
    b = a[j]
    URL = "https://de.wikipedia.org/wiki/"+b
    page = requests.get(URL)
    try:
        soup = BeautifulSoup(page.content, 'html.parser')
        l = soup.find(class_="firstHeading")
        zr = soup.find(class_="wikitable infobox infoboxstaat float-right")
        z = zr.findAll("tr")
        a=""
        #don't do this! should be 'for i in z' or something other variable name
        for z in z:
            a=a+z.text
            h=a.find("Hauptstadt")
            lol=a[h:-1]
            lol=lol.replace("Hauptstadt", "")
            lol=lol.strip()
            fg=lol.find("\n")
            lol=lol[0:fg]
            lol=lol.strip()
            j=j+1
            print(lol)
            print(l.text)
    except:
        pass

В этом примере любая страница, не имеющая правильных тегов html, будет пропущена.

0 голосов
/ 14 апреля 2020

NoneType означает, что ваша строка zr = soup.find(class_="wikitable infobox infoboxstaat float-right") ничего не возвратила.

Ошибка в этом l oop:

  for Lx in Lx:
      a.append(Lx.text)

Вы не можете использовать то же имя там. Пожалуйста, попробуйте вместо этого использовать l oop и дайте мне знать, как оно работает:

  for L in Lx:
         a.append(Lx.text)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...