Не удалось получить доступ к некоторым тегам на сайте для веб-скрейпинга

Я пытаюсь получить данные о поездке Citibike из Интернета. Поскольку есть несколько файлов, которые я хочу загрузить, я подумал, что лучше автоматизировать это с помощью python, получив доступ к нужным ссылкам, а затем используя другие методы для их загрузки.

вот мой код:

url = 'https://s3.amazonaws.com/tripdata/index.html'
html_source = requests.get(url).text 
soup = BeautifulSoup(html_source, "html.parser")
soup.prettify() 

# I'm successful until I add '.find_all('tr')' at the end
citibikedata = soup.find('tbody', id = "tbody-content").find_all('tr') 
print(citibikedata)

Не удалось получить доступ к некоторым тегам на сайте для веб-скрейпинга

При попытке распечатать получаю пустой list. Если я делаю длину (len), я получаю 0. Однако, если я уберу find_all(), я получу результаты только для tbody-content.

Я подозреваю, что по какой-то причине я не могу получить доступ к тегу tr. Между тем, есть еще один уровень тега, «td», к которому я должен получить доступ, чтобы получить данные, которые я действительно ищу, а именно href и текст в теге a.

Пожалуйста, что мне не хватает, я буду признателен за вашу помощь. Спасибо заранее

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

Все эти элементы tr загружаются динамически. Их нет в исходном HTML.

Robby Cornelissen 13.04.2023 06:04
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
1
63
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вам нужна помощь от селена:

#pip install selenium
from selenium import webdriver
from bs4 import BeautifulSoup
import time
​
url = "https://s3.amazonaws.com/tripdata/index.html"
​
with webdriver.Chrome() as driver:
    driver.get(url)
    time.sleep(5)
    tag = BeautifulSoup(driver.page_source, "html.parser").find_all("a")
    links = [link.get("href") for link in tag if link.get("href")]
​

Выход :

#links

['https://s3.amazonaws.com/tripdata/201306-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201307-201402-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201307-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201308-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201309-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201310-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201311-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201312-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201401-citibike-tripdata.zip',
 ...

Этот ответ сработал, и я хотел бы отметить его тоже, но я могу отметить только один. Я выбрал ответ от @HedgeHog по двум причинам: 1. Он с наименьшим количеством строк кода 2. Я знаком с BeautifulSoup, а не с Selenium, который используется здесь. Преимущество этого ответа: 1. Selenium лучше подходит для динамической очистки сайта. Кое-что, что я узнал в этом процессе и поэтому включу в свой план обучения. Большое спасибо

AyG 15.04.2023 17:00

Многие дороги ведут в ром — ваше объяснение позволяет легко понять, почему вы выбрали именно свою, и, возможно, вы выберете другую в другом проекте. Чтобы выразить свое спортивное мастерство, найдите минутку и прочитайте stackoverflow.com/help/привилегии/голосование, это также позволит вам соблюдать любые / другие полезные ответы.

HedgeHog 15.04.2023 18:22

В приведенном выше коде, если вы проверите:

citibikedata = soup.find('tbody', id = "tbody-content")
print(citibikedata)
>> <tbody id = "tbody-content">
   </tbody>

Хотя вы можете получить тег tbody, он не содержит никаких данных внутри, и вы получаете пустой список, когда пытаетесь найти в нем теги tr.

Но вы можете достичь своей цели, используя Selenium.

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

from selenium.webdriver import Chrome
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
import selenium.webdriver.support.expected_conditions as EC
from bs4 import BeautifulSoup

url = 'https://s3.amazonaws.com/tripdata/index.html'
driver = Chrome()
driver.get(url)

WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, 'tbody#tbody-content')))
html_source = driver.page_source
soup = BeautifulSoup(html_source, "html.parser")

citibikedata = soup.find('tbody', id = "tbody-content").find_all('tr')
print(citibikedata)

Ситибайкданные:

[<tr>
<td><i class = "icon-file i-file-or-folder" style = "margin-left:calc((1 * 16px) + 4px);"></i>
<a href = "https://s3.amazonaws.com/tripdata/201306-citibike-tripdata.zip">201306-citibike-tripdata.zip</a>
</td>
<td>Apr 30th 2018, 08:18:55 pm</td>
<td>16.79 MB</td>
<td>ZIP file</td>
</tr>, 
...
...
<tr>
<td><i class = "icon-file i-file-or-folder" style = "margin-left:calc((1 * 16px) + 4px);"></i>
<a href = "https://s3.amazonaws.com/tripdata/index.html">index.html</a>
</td>
<td>Jan 19th 2017, 05:23:41 am</td>
<td>6 KB</td>
<td>HTML file</td>
</tr>
]
Ответ принят как подходящий

Основная проблема здесь в том, что данные, как уже упоминалось, загружаются динамически, поэтому вы можете получить их из источника, из которого они получены.

https://s3.amazonaws.com/tripdata предоставит XML-файл, содержащий ваши данные, просто повторите его элементы и выберите свои URL-адреса.

Пример
import requests
from bs4 import BeautifulSoup

base_url = 'https://s3.amazonaws.com/tripdata/'
links = [
         base_url+key.text
         for key in BeautifulSoup(requests.get(base_url).text).select('Key')
        ]
links
Выход
['https://s3.amazonaws.com/tripdata/201306-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201307-201402-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201307-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201308-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201309-citibike-tripdata.zip',
 'https://s3.amazonaws.com/tripdata/201310-citibike-tripdata.zip',...]

Основываясь на вашем комментарии, вы можете использовать dict или list из dicts:

import requests
from bs4 import BeautifulSoup

base_url = 'https://s3.amazonaws.com/tripdata/'

data = []
         
for e in BeautifulSoup(requests.get(base_url).text).select('Contents'):
        data.append({
                'url':base_url+e.key.text,
                'date': e.lastmodified.text
        })
data

Большое спасибо за вашу помощь @HedgeHog. Мне тоже нужна дата. Я могу либо использовать тег «LastModified», либо удалить ключ для года/мм (например, 201306), любой из этих способов мне подходит. Мой вопрос: как мне добиться любой из них и даты, чтобы сопровождать ссылку как одну и ту же запись, в то время как между каждой последующей записью есть пробел?

AyG 13.04.2023 18:41

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

HedgeHog 14.04.2023 07:41

Другие вопросы по теме