Соскребая инфобокс Википедии, когда ячейки таблицы находятся в смешанных форматах - PullRequest
0 голосов
/ 10 января 2019

Я пытаюсь почистить инфобокс Википедии и получить информацию по некоторым ключевым словам. Например: https://en.wikipedia.org/wiki/A%26W_Root_Beer

image

Допустим, я ищу значения для производителя. Я хочу их в списке, и я хочу только их текст. Таким образом, в этом случае желаемый результат будет ['Keurig Dr Pepper (United States, Worldwide)', 'A&W Canada (Canada)']. Что бы я ни пытался, я не могу успешно создать этот список. Вот кусок моего кода:

url = "https://en.wikipedia.org/wiki/ABC_Studios"
soup = BeautifulSoup(requests.get(url), "lxml")
tbl = soup.find("table", {"class": "infobox vcard"})
list_of_table_rows = tbl.findAll('tr')
for tr in list_of_table_rows:

        th = tr.find("th")
        td = tr.find("td")

    # take th.text and td.text

Мне нужен метод, который может работать в различных случаях: когда в пути есть разрывы строк, когда некоторые значения являются ссылками, когда некоторые значения являются абзацами и т. Д. Во всех случаях мне нужно только текст, который мы видим на экране, а не ссылка, не абзац, просто текст. Я также не хочу, чтобы вывод был Keurig Dr Pepper (United States, Worldwide)A&W Canada (Canada), так как позже я хотел бы иметь возможность анализировать результат и что-то делать с каждой сущностью.

Есть много страниц Википедии, которые я прохожу, и я не могу найти метод, который бы работал на значительную их часть. Не могли бы вы помочь мне с рабочим кодом ? Я не разбираюсь в соскобах.

Ответы [ 2 ]

0 голосов
/ 10 января 2019

этот код не будет работать

soup = BeautifulSoup(requests.get(url), "lxml")

BeautifulSoup нужен контент requests, добавьте .text или .content.

Чтобы получить ожидаемый результат для производства, вам нужно выбрать элемент a в td[class="brand"], затем использовать .next_sibling.string

html = requests.get(url).text
soup = BeautifulSoup(html, 'lxml')
result = soup.select('td[class="brand"] a')
manufacturer = [a.text + a.next_sibling.string for a in result]
print(manufacturer)
# ['Keurig Dr Pepper (United States, Worldwide)', 'A&W Canada (Canada)']
0 голосов
/ 10 января 2019

Хорошо, вот моя попытка сделать это (библиотека json предназначена только для красивой печати словаря):

import json
from bs4 import BeautifulSoup
import requests

url = "https://en.wikipedia.org/wiki/ABC_Studios"
r = requests.get(url)
soup = BeautifulSoup(r.text, "lxml")
tbl = soup.find("table", {"class": "infobox vcard"})

list_of_table_rows = tbl.findAll('tr')
info = {}
for tr in list_of_table_rows:

        th = tr.find("th")
        td = tr.find("td")
        if th is not None:
            innerText = ''
            for elem in td.recursiveChildGenerator():
                if isinstance(elem, str):
                    innerText += elem.strip()
                elif elem.name == 'br':
                    innerText += '\n'
            info[th.text] = innerText

print(json.dumps(info, indent=1))

Код заменяет теги <br/> на \n, что дает:

{
 "Trading name": "ABC Studios",
 "Type": "Subsidiary\nLimited liability company",
 "Industry": "Television production",
 "Predecessor": "Touchstone Television",
 "Founded": "March\u00a021, 1985; 33 years ago(1985-03-21)",
 "Headquarters": "Burbank, California,U.S.",
 "Area served": "Worldwide",
 "Key people": "Patrick Moran (President)",
 "Parent": "ABC Entertainment Group\n(Disney\u2013ABC Television Group)",
 "Website": "abcstudios.go.com"
}

Вы можете настроить его, если хотите возвращать списки вместо строк с помощью \n s

    innerTextList = innerText.split("\n")
    if len(innerTextList) < 2:
        info[th.text] = innerTextList[0]
    else:
        info[th.text] = innerTextList

Что дает:

{
 "Trading name": "ABC Studios",
 "Type": [
  "Subsidiary",
  "Limited liability company"
 ],
 "Industry": "Television production",
 "Predecessor": "Touchstone Television",
 "Founded": "March\u00a021, 1985; 33 years ago(1985-03-21)",
 "Headquarters": "Burbank, California,U.S.",
 "Area served": "Worldwide",
 "Key people": "Patrick Moran (President)",
 "Parent": [
  "ABC Entertainment Group",
  "(Disney\u2013ABC Television Group)"
 ],
 "Website": "abcstudios.go.com"
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...