Python - 覆盖多个url的网页抓取数据表

标签 python web-scraping beautifulsoup

Python 的新手,但我真的很想学习它。我正在尝试从网站上抓取数据,感觉我已经非常接近找到解决方案了。问题是它一直只返回 url 的第一页,即使代码中的 url 在每次迭代时都更改了页码。

我使用的网站是http://etfdb.com/etf/SPY/#etf-holdings&sort_name=weight&sort_order=desc&page=1我试图抓取的具体数据表是 SPY Holdings(其中显示 506 股,然后列出苹果、微软等)

正如您所注意到的,数据表有一堆页面(并且这会根据股票代码而变化 - 但出于此目的,请注意尽管 SPY 有 34 页,但它不会总是 34 页).它首先显示 15 家公司,然后当您单击 2(以查看接下来的 15 家公司)时,url page= 上升 1。

#to break up html
from bs4 import BeautifulSoup as soup
from urllib.request import urlopen as uReq
import csv
import math

#goes to url - determines the number of holdings and the number of pages the data table will need to loop through
my_url = "http://etfdb.com/etf/SPY/#etf-
holdings&sort_name=weight&sort_order=desc&page=1"
uClient = uReq(my_url)
page_html = uClient.read()
uClient.close()
page_soup = soup(page_html,"html.parser")
#goes to url - scrapes from another section of the page and finds 506 holdings
num_holdings_text = page_soup.find('span',{'class': 'relative-metric-bubble-data'})
num_holdings = num_holdings_text.text
number_of_loops = int(num_holdings)
num_of_loops = number_of_loops/15
#goes to url - because the table shows 15 holdings at a time, this calcs number of pages I'll need to loop through
num_of_loops = math.ceil(num_of_loops)
holdings = []
for loop in range(1,num_of_loops+1):
    my_url = "http://etfdb.com/etf/SPY/#etf-holdings&sort_name=weight&sort_order=desc&page=" + str(loop)
    uClient = uReq(my_url)
    page_html = uClient.read()
    uClient.close()
    page_soup = soup(page_html, "html.parser")
    table = page_soup.find('table', {
    'class': 'table mm-mobile-table table-module2 table-default table-striped table-hover table-pagination'})
    table_body = table.find('tbody')
    table_rows = table_body.find_all('tr')
    for tr in table_rows:
        td = tr.find_all('td')
        row = [i.text.strip() for i in td]
        holdings.append(row)
        print(row)
    print (holdings)


    with open('etfdatapull2.csv','w',newline='') as fp:
        a = csv.writer(fp, delimiter = ',')
        a.writerows(holdings)

同样,我遇到的问题是它只是不断返回第一页(例如,它总是只返回 apple - GE),即使链接正在更新。

非常感谢您的帮助。再次强调,这对它来说非常新,所以请尽可能简化它!

最佳答案

问题是您尝试抓取的网站实际上是在事后通过 Javascript 加载数据的。如果您使用 Chrome 开发者工具之类的东西,您可以在第 2 页看到该网站引用以下链接:

http://etfdb.com/data_set/?tm=1699&cond={by_etf:325}&no_null_sort=true&count_by_id=&sort=weight&order=desc&limit=15&offset=15

你要找的数据就在那里;你的逻辑是合理的,但你只需要抓取上面的链接。

如果您删除“offset”参数,并将限制更改为 1000,您实际上会一次获得所有数据,并且您可以完全删除分页。

希望对您有所帮助!

编辑:我应该指出,您加载的页面总是相同的(第一组条目,以 AAPL 开头),然后数据由 Javascript 从上面的资源加载。然后 Javascript 替换您正在抓取的 HTML 的内容。由于您的脚本查看原始 HTML(但不执行替换内容的 Javascript),因此您一遍又一遍地得到相同的表格。

关于Python - 覆盖多个url的网页抓取数据表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45971243/

相关文章:

python - Django - 生产中特定 View 的等待时间太长

javascript - 将 JavaScript 注入(inject)浏览器对话框

python - 尝试制作网络爬虫来解析网站链接时接收和空列表

python-3.x - 在 Python 3.2 中使用 HTMLParser

Python-无法使用 BeautifulSoup 定位 CSS 类

python - 为 Python (Windows) 正确安装 pyOpenSSL

python - 转换数据框 - Python

python - 抓取特定文本的嵌套网页

python - 对列多个文件 Pandas 的操作

python - BeautifulSoup findAll 和 findChildren 之间的区别