python-3.x - 如何让 phantomJS webdriver 等到加载特定的 HTML 元素然后返回 page.source?
问题描述
我为网络爬取对象开发了下面的代码。
它需要两个日期作为输入。然后在这两个日期之间创建一个日期列表,并将每个日期附加到包含某个位置的天气信息的网页 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
在网页完全加载网页内容之前返回的,包括表格(包含天气信息)。网站也有可能拒绝该请求,因为它使服务器太忙。
无论如何,我们是否可以构建一个循环,不断尝试打开链接,直到它可以找到表格,或者至少等到表格加载然后返回表格?
解决方案
您可以让 selenium 等待特定元素。在您的情况下,它将是类名为“tablesaw-sortable”的表。我强烈建议您使用 CSS 选择器来查找此元素,因为它可以快速获取所有表格元素且不易出错。
这是为您预制的 CSS 选择器table.tablesaw-sortable
。将 selenium 设置为等到该元素加载完毕。
推荐阅读
- c++ - 在 vscode 中包含头文件时没有此类文件或目录错误
- python - Gunicorn 工人以信号 9 终止
- html - selectinput 函数不会在 UI 中一次显示整个列表
- c# - 使用特定数字模拟 SqlException
- reactjs - 我无法访问 NEXTAUTH_URL,因为我无法使用 NEXT_PUBLIC 访问它
- libjpeg - 抑制警告:量化表对于基线 JPEG 来说太粗糙了
- html - 如何将自定义样式添加到 Angular Material Table 单元格的一小部分?
- java - 如何计算字符串中每个单词的字母[]
- java - 将一种枚举类型转换为另一种枚举类型的通用方法
- php - 如果“删除”会抱怨缺少依赖项,如何替换提供“php-http/async-client-implementation”的包?