Я разработал приведенный ниже код для объекта сканирования в Интернете.
Он принимает две даты в качестве входных данных. Затем создается список дат между этими двумя датами и прикрепляется каждая к URL-адресу веб-страницы, который содержит информацию о погоде.местоположения.Затем он преобразует HTML-таблицы данных в Dataframe, а затем сохраняет данные в виде CSV-файла в хранилище (базовая ссылка: https://www.wunderground.com/history/daily/ir/mashhad/OIMM/date/2019-1-3, и, как вы можете видеть в этом примере, дата 2019-1-3):
from datetime import timedelta, date
from bs4 import BeautifulSoup
from selenium import webdriver
import pandas as pd
from furl import furl
import os
import time
class WebCrawler():
def __init__(self, st_date, end_date):
if not os.path.exists('Data'):
os.makedirs('Data')
self.path = os.path.join(os.getcwd(), 'Data')
self.driver = webdriver.PhantomJS()
self.base_url = 'https://www.wunderground.com/history/daily/ir/mashhad/OIMM/date/'
self.st_date = st_date
self.end_date = end_date
def date_list(self):
# Create list of dates between two dates given as inputs.
dates = []
total_days = int((self.end_date - self.st_date).days + 1)
for i in range(total_days):
date = self.st_date + timedelta(days=i)
dates.append(date.strftime('%Y-%m-%d'))
return dates
def create_link(self, attachment):
# Attach dates to base link
f = furl(self.base_url)
f.path /= attachment
f.path.normalize()
return f.url
def open_link(self, link):
# Opens link and visits page and returns html source code of page
self.driver.get(link)
html = self.driver.page_source
return html
def table_to_df(self, html):
# Finds table of weather data and converts it into pandas dataframe and returns it
soup = BeautifulSoup(html, 'lxml')
table = soup.find("table",{"class":"tablesaw-sortable"})
dfs = pd.read_html(str(table))
df = dfs[0]
return df
def to_csv(self, name, df):
# Save the dataframe as csv file in the defined path
filename = name + '.csv'
df.to_csv(os.path.join(self.path,filename), index=False)
Вот как я хочу использовать объект WebCrawler
:
date1 = date(2018, 12, 29)
date2 = date(2019, 1, 1)
# Initialize WebCrawler object
crawler = WebCrawler(st_date=date1, end_date=date2)
dates = crawler.date_list()
for day in dates:
print('**************************')
print('PROCESSING : ', day)
link = crawler.create_link(day)
print('WAITING... ')
time.sleep(3)
print('VISIT WEBPAGE ... ')
html = crawler.open_link(link)
print('DATA RETRIEVED ... ')
df = crawler.table_to_df(html)
print(df.head(3))
crawler.to_csv(day, df)
print('DATA SAVED ...')
Проблема, которая возникает, состоит в том, что первая итерация цикла выполняется идеально, а вторая останавливается сошибка, которая говорит No tables where found
(встречается в строке table = soup.find("table",{"class":"tablesaw-sortable"})
), и это потому, что источник страницы возвращается WebCrawler.open_link
до того, как веб-страница полностью загрузит содержимое веб-страницы, включая таблицу (содержащую информацию о погоде).также существует вероятность того, что веб-сайт отклонит запрос, потому что это делает серверы слишком загруженными.
В любом случае можно ли создать цикл, который будет продолжать пытаться открыть ссылку до тех пор, пока он не сможет найти таблицу, или вподождать, пока таблица загрузится, а затем вернуть таблицу?