BeautifulSoup не может найти тег XML, как мне это исправить? - PullRequest
0 голосов
/ 31 декабря 2018

Попытка с помощью Beautifulsoup очистить сайт магазина, с помощью findAll('url') возвращает пустой список.Как мне получить желаемый контент?

import requests
from bs4 import BeautifulSoup as soupify
import lxml

webSite = requests.get('https://launch.toytokyo.com/sitemap_pages_1.xml')
pageSource = webSite.text
webSite.close()

pageSource = soupify(pageSource, "xml")
print(pageSource.findAll('url'))

Страница, которую я пытаюсь почистить: https://launch.toytokyo.com/sitemap_pages_1.xml

Что я получаю: пустой список

Что я должен получить: не пустой список

Спасибо всем за помощь, выяснил проблему в моем коде, я использовал более старую версию findAll вместо find_all

Ответы [ 4 ]

0 голосов
/ 31 декабря 2018

Я пытался показать точно, как вы уже пробовали.Единственное, что вам нужно исправить - это webSite.text.Вы могли бы получить действительный ответ, если бы вместо этого использовали webSite.content.

Это исправленная версия вашей существующей попытки:

import requests
from bs4 import BeautifulSoup

webSite = requests.get('https://launch.toytokyo.com/sitemap_pages_1.xml')
pageSource = BeautifulSoup(webSite.content, "xml")
for k in pageSource.find_all('url'):
    link = k.loc.text
    date = k.lastmod.text
    frequency = k.changefreq.text
    print(f'{link}\n{date}\n{frequency}\n')
0 голосов
/ 31 декабря 2018

В качестве альтернативы BeautifulSoup вы всегда можете использовать xml.etree.ElementTree для анализа ваших URL-адресов XML, расположенных в теге loc:

from requests import get
from xml.etree.ElementTree import fromstring, ElementTree
from pprint import pprint

url = 'https://launch.toytokyo.com/sitemap_pages_1.xml'

req = get(url)
tree = ElementTree(fromstring(req.text))

urls = []
for outer in tree.getroot():
    for inner in outer:
        namespace, tag = inner.tag.split("}")
        if tag == 'loc':
            urls.append(inner.text)

pprint(urls)

, что дастследующие URL-адреса в списке:

['https://launch.toytokyo.com/pages/about',
 'https://launch.toytokyo.com/pages/help',
 'https://launch.toytokyo.com/pages/terms',
 'https://launch.toytokyo.com/pages/visit-us']

Отсюда вы можете сгруппировать свою информацию в collections.defaultdict:

from requests import get
from xml.etree.ElementTree import fromstring, ElementTree
from collections import defaultdict
from pprint import pprint

url = 'https://launch.toytokyo.com/sitemap_pages_1.xml'

req = get(url)
tree = ElementTree(fromstring(req.text))

data = defaultdict(dict)
for i, outer in enumerate(tree.getroot()):
    for inner in outer:
        namespace, tag = inner.tag.split("}")
        data[i][tag] = inner.text

pprint(data)

, что дает следующий defaultdict изсловари с индексами в качестве ключей:

defaultdict(<class 'dict'>,
            {0: {'changefreq': 'weekly',
                 'lastmod': '2018-07-26T14:37:12-07:00',
                 'loc': 'https://launch.toytokyo.com/pages/about'},
             1: {'changefreq': 'weekly',
                 'lastmod': '2018-11-26T07:58:43-08:00',
                 'loc': 'https://launch.toytokyo.com/pages/help'},
             2: {'changefreq': 'weekly',
                 'lastmod': '2018-08-02T08:57:58-07:00',
                 'loc': 'https://launch.toytokyo.com/pages/terms'},
             3: {'changefreq': 'weekly',
                 'lastmod': '2018-05-21T15:02:36-07:00',
                 'loc': 'https://launch.toytokyo.com/pages/visit-us'}})

Если вы хотите вместо этого группировать по категориям, вы можете вместо этого использовать defaultdict списков:

data = defaultdict(list)
for outer in tree.getroot():
    for inner in outer:
        namespace, tag = inner.tag.split("}")
        data[tag].append(inner.text)

pprint(data)

, что дает такую ​​другую структуру:

defaultdict(<class 'list'>,
            {'changefreq': ['weekly', 'weekly', 'weekly', 'weekly'],
             'lastmod': ['2018-07-26T14:37:12-07:00',
                         '2018-11-26T07:58:43-08:00',
                         '2018-08-02T08:57:58-07:00',
                         '2018-05-21T15:02:36-07:00'],
             'loc': ['https://launch.toytokyo.com/pages/about',
                     'https://launch.toytokyo.com/pages/help',
                     'https://launch.toytokyo.com/pages/terms',
                     'https://launch.toytokyo.com/pages/visit-us']})
0 голосов
/ 31 декабря 2018

Другой способ использования xpath

import requests
from lxml import html
url = 'https://launch.toytokyo.com/sitemap_pages_1.xml'
tree = html.fromstring( requests.get(url).content)
links = [link.text for link in tree.xpath('//url/loc')]
print(links)
0 голосов
/ 31 декабря 2018

Вы можете сделать:

import requests
from bs4 import BeautifulSoup as bs

url = 'https://launch.toytokyo.com/sitemap_pages_1.xml'

soup = bs(requests.get(url).content,'html.parser')


urls = [i.text for i in soup.find_all('loc')]

Поэтому в основном я получаю содержимое и нахожу тег loc, содержащий URL-адреса, а затем беру содержимое;)

Обновлено: Обязательный тег URL исгенерировать словарь

urls = [i for i in soup.find_all('url')]

s = [[{k.name:k.text} for k in urls[i] if not isinstance(k,str)] for i,_ in enumerate(urls)]

Использовать из pprint import pprint as print, чтобы получить красивый отпечаток s:

print(s)

Примечания: вы можете использовать анализатор lxml, так как он работает быстрее, чем html.парсер

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...