【问题标题】:HTML stuck at page 1 pythonHTML卡在第1页python
【发布时间】:2020-02-27 10:46:25
【问题描述】:

我正在尝试使用requestslxml.htmlpackages 为给定网页构建网络爬虫。

当我尝试迭代它的页面时,似乎我总是得到第一页的 html。理想情况下,我想检索每个页面的主表的内容并将其存储在 pandas df 中。

我的代码失败的任何建议?我正在使用 python 3.7.4 和 Ubuntu 操作系统

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)


【问题讨论】:

  • 我没有看到您正在使用 pagedoc 做任何事情。你能包括其余的代码吗?
  • 就像@Dinac23 说的。如果你想获得 another 页面,你需要制作 another requests.get 你没有这样做。顺便说一句,您的代码不可重现,请提供其余部分。
  • @Dinac23 我刚刚更新了代码,我错过了一部分。我在for循环中动态更改url,不应该更新“page”和“doc”变量吗?
  • @eusoubrasileiro 我刚刚更新了代码,我错过了一部分。我在for循环中动态更改url,不应该更新“page”和“doc”变量吗?
  • @AxelBorasinoDiBola 它接缝那个页面是问题所在。我很简单的GET 将无法使用它。尝试在Google chromeFirefox 上使用inspect 来查看您的浏览器正在生成的请求标头并从中工作。

标签: python html ubuntu web-scraping python-requests


【解决方案1】:

page = requests.get(url)这行之后添加一些延迟,请求库需要一些时间来获取页面内容,但循环执行速度比这更快

【讨论】:

  • 延迟什么都不做,requests.get 是一个同步操作,所以代码执行将停止,直到我们收到响应。
【解决方案2】:

经过一番研究和时间,我终于可以用 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

【讨论】:

    【解决方案3】:

    问题不在于代码,而在于网站本身。您不能像现在这样抓取这些表格,因为这些表格是异步模板,并且它们需要时间来加载具有您期望的页码的实际表格。

    比方说,加载页面值为 5 的 url - 首先它使用第 1 页数据加载表格,然后使用第 5 页数据加载表格

    尝试了解具有这些 url 值的表是如何加载的,您会注意到同样的情况。

    我认为我们无法修复您的代码中的某些内容来完成此操作,请使用 selenium 在这些情况下非常有用。

    如果我错了,请纠正我。

    【讨论】:

      【解决方案4】:

      我刚刚修改了您的代码以使其正常工作,请检查:-

      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)
      

      【讨论】:

      • 感谢您的回复,但这并不能解决错误。如果你检查 df 你会看到只有第一页的前 25 行重复了 15 次。
      猜你喜欢
      • 1970-01-01
      • 2020-03-28
      • 2014-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多