В этом коде и в том, как вы используете библиотеки, есть немало примечательных проблем.Позвольте мне попытаться исправить это.
Во-первых, я не вижу, чтобы вы использовали библиотеку urllib.request
.Вы можете удалить это, или если вы используете его в другом месте вашего кода, я рекомендую высоко оцененный модуль запросы .Я также рекомендую использовать библиотеку запросов вместо selenium, если вы пытаетесь получить только источник HTML с сайта, поскольку selenium больше ориентирован на навигацию по сайтам и действует как «реальный» человек.
Вы можетеиспользуйте response = requests.get('https://your.url.here')
, а затем response.text
, чтобы получить возвращенный HTML.
Далее я заметил, что в методе open_link()
вы создаете новый экземпляр класса PhantomJS
каждый раз, когда вызываете метод.Это действительно неэффективно, поскольку селен использует много ресурсов (и занимает много времени, в зависимости от используемого вами драйвера).Это может быть большой вклад в ваш код работает медленнее, чем хотелось бы.Вы должны максимально использовать экземпляр driver
, поскольку селен был разработан для такого использования.Отличным решением этой проблемы было бы создание экземпляра driver
в методе * 1016. *
class WebCrawler():
def __init__(self, st_date, end_date):
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 open_link(self, link):
self.driver.get(link)
html = driver.page_source
return html
# Alternatively using the requests library
class WebCrawler():
def __init__(self, st_date, end_date):
self.base_url = 'https://www.wunderground.com/history/daily/ir/mashhad/OIMM/date/'
self.st_date = st_date
self.end_date = end_date
def open_link(self, link):
response = requests.get(link)
html = response.text
return html
Примечание: для имен классов следует использовать CamelCase вместо строчных.Это всего лишь предложение, но оригинальный создатель python создал PEP8, чтобы определить общее руководство по стилю написания кода на python.Проверьте это здесь: Имена классов
Еще одна странная вещь, которую я обнаружил, это то, что вы приводите строку в ... строку.Вы делаете это в url = str(self.base_url)
.Это ничего не ранит, но и не помогает.Я не могу найти какие-либо ресурсы / ссылки, но у меня есть подозрение, что это займет дополнительное время для переводчика.Поскольку скорость имеет значение, я рекомендую использовать url = self.base_url
, поскольку базовый URL-адрес уже является строкой.
Я вижу, что вы форматируете и создаете URL-адреса вручную, но если вы хотите немного больше контроля и меньшеошибки, посмотрите библиотеку furl .
def create_link(self, attachment):
f = furl(self.base_url)
# The '/=' operator means append to the end, docs: https://github.com/gruns/furl/blob/master/API.md#path
f.path /= attachment
# Cleanup and remove invalid characters in the url
f.path.normalize()
return f.url # returns the url as a string
Другая потенциальная проблема заключается в том, что метод extract_table()
ничего не извлекает, он просто форматирует html так, как это делает человек.удобочитаемый.Я не буду углубляться в это, но я рекомендую изучить CSS-селекторы или XPath-селекторы для простого извлечения данных из HTML.
В методе date_list()
вы пытаетесь использовать переменную date1
,но не определили это нигде.Я разбил бы там лямбду и расширил бы ее на несколько строк, чтобы вы могли легко прочитать и понять, что она пытается делать.
Ниже приведен полный, переработанный, , предложенный код.
from datetime import timedelta, date
from bs4 import BeautifulSoup
import requests
from furl import furl
class WebCrawler():
def __init__(self, st_date, end_date):
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):
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):
f = furl(self.base_url)
# The '/=' operator means append to the end, docs: https://github.com/gruns/furl/blob/master/API.md#path
f.path /= attachment
# Cleanup and remove invalid characters in the url
f.path.normalize()
return f.url # returns the url as a string
def open_link(self, link):
response = requests.get(link)
html = response.text
return html
def extract_table(self, html):
soup = BeautifulSoup(html)
print(soup.prettify())
def output_to_csv(self):
pass
date1 = date(2018, 3, 1)
date2 = date(2019, 3, 5)
test = webcrawler(st_date=date1, end_date=date2)
date_list = test.date_list()
link = test.create_link(date_list[0])
html = test.open_link(link)
test.extract_table(html)