HTML застрял на странице 1 python - PullRequest
0 голосов
/ 27 февраля 2020

Я пытаюсь создать веб-браузер для данной веб-страницы с пакетами requests и lxml.html.

Когда я пытаюсь перебрать его страницы, мне кажется, что я всегда получаю html первой страницы. В идеале я хотел бы получить содержимое главной таблицы каждой страницы и сохранить его в pandas df. ​​

Любое предложение, где мой код не работает? Я работаю с python 3.7.4 и Ubuntu OS

import requests
import lxml.html as lh
import pandas as pd

base_url = "https://etfdb.com/etfs/asset-class/#etfs&sort_name=assets_under_management&sort_order=desc&page="

n_pages = 15
data = []
for i in range(1,n_pages+1):
    url = base_url+str(i)            
    page = requests.get(url)    
    doc = lh.fromstring(page.content)

    # Retrieve all tr_like elements (table rows)
    tr_elements = doc.xpath('//tr') 

    #Create a columns vector to create our df
    col = list(filter(None,tr_elements[0].text_content().split("\n")))

    #Iterate over the rows of the table
    for j in range(1,len(tr_elements)-1):
        row = tr_elements[j]

        #Since there are multiple tables in the webpage, make sure
        #we are retrieving the rows of the correct one
        if len(row)==len(col):
            data.append([value.text_content() for value in row.iterchildren()])
        else:
            print("Ignoring data")

df =  pd.DataFrame(data,columns=col)


Ответы [ 4 ]

0 голосов
/ 17 марта 2020

После некоторых исследований и времени я наконец-то смог очистить страницу с помощью Selenium. Несмотря на то, что есть несколько не очень элегантных обходных путей (например, ожидание фиксированного количества секунд для загрузки страницы или извлечение собственного HTML для некоторых полей), код успешно извлекает поля в n столбцах желаемой таблицы на нескольких страницах ( указывается пользователем). Наконец, создается фрейм данных со всей информацией. (Используется версия Python 3.6 и ОС Ubuntu)

from selenium import webdriver
import pandas as pd
import time

values = {}
delay = 10 # seconds
n_pages = 10
for i in range(1,n_pages):
    driver = webdriver.Chrome()
    url = 'https://etfdb.com/etfs/asset-class/#etfs&sort_name=assets_under_management&sort_order=desc&page='
    page = url+str(i)
    driver.get(page)

    # After doing the query, wait delay seconds until is fully loaded
    time.sleep(delay)

    # Retrieve all rows excep the header and bottom
    table_id = driver.find_element_by_class_name('fixed-table-body')
    rows = table_id.find_elements_by_tag_name('tr')[1:-1]
    for row in rows:
        fields = row.find_elements_by_tag_name('td')
        ticker = fields[0].text
        name = fields[1].text
        ass_class,aum = fields[2].text,fields[3].text[1:]

        # For some reason I don't know, get_attribute text delivered
        # blank results for the two following fields, that is why
        # I needed to retrieve the innerHTML and parse it from there
        etf_category = fields[19].get_attribute("innerHTML").split('>')[1].split('<')[0].strip().lower()
        er = float(fields[21].get_attribute("innerHTML")[:-1])

        # Populate the dict
        values[ticker] = {'name':name,'asset_class':ass_class,'Total_Assets(MM$)':aum,\
                          'ETF_category':etf_category,'Expense_ratio':er}
    # Close the url once it's been scraped   
    driver.quit()

# Create dataframe
df = pd.DataFrame(values).T
0 голосов
/ 27 февраля 2020

Я только что изменил ваш код, чтобы он работал, пожалуйста, проверьте: -

import requests
import lxml.html as lh
import pandas as pd

base_url = "https://etfdb.com/etfs/asset-class/#etfs&sort_name=assets_under_management&sort_order=desc&page="

data = []
final_url = []

for r in range(1,16): #change the upper range as per requirement
    final_url.append(base_url + str(r))
for url in final_url:     
    page = requests.get(url)    
    doc = lh.fromstring(page.content)

    # Retrieve all tr_like elements (table rows)
    tr_elements = doc.xpath('//tr') 

    #Create a columns vector to create our df
    col = list(filter(None,tr_elements[0].text_content().split("\n")))

    #Iterate over the rows of the table
    for j in range(1,len(tr_elements)-1):
        row = tr_elements[j]

        #Since there are multiple tables in the webpage, make sure
        #we are retrieving the rows of the correct one
        if len(row)==len(col):
            data.append([value.text_content() for value in row.iterchildren()])
        else:
            print("Ignoring data")

df =  pd.DataFrame(data,columns=col)
0 голосов
/ 02 марта 2020

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

Допустим, загрузить URL-адрес со значением страницы 5 - сначала он загружает таблицу с данными страницы 1, а затем загружает таблицу с данными страницы 5

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

Я не думаю, что мы можем что-то исправить в вашем коде для достижения sh этого, используйте selenium, это полезно в этом сценарии ios.

Пожалуйста, поправьте меня, если я ошибаюсь.

0 голосов
/ 27 февраля 2020

добавить некоторую задержку после этой строки page = requests.get(url), библиотеке запросов требуется некоторое время для получения содержимого страницы, но l oop выполняется быстрее, чем

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