【问题标题】:Scraping data from multiple previous dates in WSJ stocks website在 WSJ 股票网站中从多个先前日期抓取数据
【发布时间】:2015-08-08 14:43:11
【问题描述】:

我正在从 WSJ Biggest Gainers 网站抓取数据。我是 Python 新手,所以我确信这很简单。我只是找不到明确的答案。

我的代码目前只从一页下载数据,但我希望它回到前几天的数据,例如,find_all 或从图表中选择数据。如何修改代码中的 URL 来执行此操作?我正在使用 Python 3.4.3 和 bs4。

好消息是前几天的网站 URL 仅在几个数字上有所不同。

例如, 这是上周五 http://online.wsj.com/mdc/public/page/2_3021-gainnnm-gainer-20150731.html?mod=mdc_pastcalendar

这是上周四

http://online.wsj.com/mdc/public/page/2_3021-gainnnm-gainer-20150730.html?mod=mdc_pastcalendar

理想情况下,如果我愿意,我希望能够更改月份、日期或年份,然后循环不同的页面 URL 以检索我希望的数据。

这是我的代码:

import requests 
from bs4 import BeautifulSoup


url = 'http://online.wsj.com/mdc/public/page/2_3021-gainnyse-gainer.html'

r = requests.get(url)           #downloads website html

soup = BeautifulSoup(r.content)         #soup calls the data

v_data = soup.select('.text') 

for symbol in v_data:
    print(symbol.text)

我只想在过去 X 天循环这个函数。我尝试制作一个 URL 列表以运行但没有运气。制作 URL 列表也需要更多的工作,所以如果我可以使用 %s 或 %d 之类的东西来表示月、年和日期,那就更好了。

【问题讨论】:

  • 我假设 BeautifulSoup 默认不支持 JavaScript,但我想知道您的目标站点是否需要它。您是否尝试过在禁用 JS 的情况下浏览目标站点?
  • 不,我没有。如果我能找到一种查看 URL 的方法,我不必担心 JS,因为我所要更改的只是之前 URL 中对应于月份和日期的 4 个数字(例如 8 月 1 日的 0801)
  • 啊,你刚才的回答让我很困惑——听起来你不认为 JavaScript 对网络抓取很重要(这很重要)。我认为你的意思是刮板适用于一页,而你只是想生成新的 URL。对吗?
  • 是的,我就是这个意思。

标签: python beautifulsoup


【解决方案1】:

您可以使用开始日期,然后 -= 使用 timedelta 的一天,使用 str.format 和 strftime 将日期传递给 url:

import requests
from bs4 import BeautifulSoup
from datetime import date,timedelta
start_url = "http://online.wsj.com/mdc/public/page/2_3021-gainnnm-gainer-{}.html?mod=mdc_pastcalendar"

start = date.today()
for _ in range(5):
    url = start_url.format(start.strftime("%Y%m%d"))
    start -= timedelta(days=1)
    r = requests.get(url)           #downloads website html
    soup = BeautifulSoup(r.content)         #soup calls the data
    v_data = soup.select('.text')
    for symbol in v_data:
        print(symbol.text)

只需创建您想要的任何日期。如果你想要一个特定的开始日期,只需创建一个 datetime 对象:

import requests
from bs4 import BeautifulSoup
from datetime import datetime,timedelta
start_url = "http://online.wsj.com/mdc/public/page/2_3021-gainnnm-gainer-{}.html?mod=mdc_pastcalendar"

start = datetime(2015,07,31)
for _ in range(5):
    print("Data for {}".format(start.strftime("%b %d %Y")))
    url = start_url.format(start.strftime("%Y%m%d"))
    start -= timedelta(days=1)
    r = requests.get(url)           #downloads website html
    soup = BeautifulSoup(r.content)         #soup calls the data
    v_data = soup.select('.text')
    for symbol in v_data:
        print(symbol.text.rstrip())
    print(" ")

输出:

Data for Jul 31 2015

|
WHAT'S THIS?
|
1

MoneyGram International (MGI)
2

YRC Worldwide (YRCW)
3

Immersion (IMMR)
4

Skywest (SKYW)
5

Vital Therapies (VTL)
6

..........................

Data for Jul 30 2015

|
WHAT'S THIS?
|
1

H&E Equipment Services (HEES)
2

Senomyx (SNMX)
3

eHealth (EHTH)
4

Nutrisystem (NTRI)
5

Open Text (OTEX)
6

LivePerson (LPSN)
7

Sonus Networks (SONS)
8

FormFactor (FORM)
9

Pegasystems (PEGA)
10

Town Sports International Holdings (CLUB)
11

FARO Technologies (FARO)
12

Presbia (LENS)
13

如果您只想包含工作日并且仍然得到n 天,那么我们需要添加更多逻辑。

import requests
from bs4 import BeautifulSoup
from datetime import datetime, timedelta

start_url = "http://online.wsj.com/mdc/public/page/2_3021-gainnnm-gainer-{}.html?mod=mdc_pastcalendar"

start = datetime(2015, 7, 31)


def only_weekdays_range(start, n):
    i = 0
    wk_days = {0, 1, 2, 3, 4}
    while i != n:
        while start.weekday() not in wk_days:
            start -= timedelta(days=1)
        yield start
        i += 1
        start -= timedelta(days=1)



for dte in (only_weekdays_range(start, 2)):
    print("Data for {}".format(start.strftime("%b %d %Y")))
    url = start_url.format(start.strftime("%Y%m%d"))
    print(url)
    r = requests.get(url)  #downloads website html
    soup = BeautifulSoup(r.content)  #soup calls the data
    v_data = soup.select('.text')
    for symbol in v_data:
        print(symbol.text.rstrip())
    print(" ")

only_weekdays_range 将从我们的开始日期起获得n 天,不包括周末。您可以通过以下方式进行:print(list(only_weekdays_range(datetime(2015, 7, 26), 2)))。我们得到[datetime.datetime(2015, 7, 24, 0, 0), datetime.datetime(2015, 7, 23, 0, 0)],星期五是24th,星期四是23rd,因为我们的开始日是星期天26th

如果您还想排除节假日,那就需要做更多的工作。另一种方法是仅在您从v_data 返回数据时减少n,但这可能会由于各种原因导致无限循环。

【讨论】:

  • 非常感谢。这是一个非常有帮助的答案。
  • 我的回报与“开始”相同,并且与“for”循环中输入的次数相同。而不是复古抓取 2 天,我得到了 2 个开始数据的副本......我错过了什么吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多