python抓取动态网页(我该怎么办抓取动态加载的网站() )
优采云 发布时间: 2022-01-13 23:05python抓取动态网页(我该怎么办抓取动态加载的网站()
)
这是我第一次获取动态加载的网站,我一直在尝试获取该网站的团队名称和赔率
我在这个 文章
中用 PyQt5 试过这个
从 PyQt4 到 PyQt5 -> mainFrame() 已弃用,需要修复才能加载网页
class Page(QWebEnginePage):
def __init__(self, url):
self.app = QApplication(sys.argv)
QWebEnginePage.__init__(self)
self.html = ''
self.loadFinished.connect(self._on_load_finished)
self.load(QUrl(url))
self.app.exec_()
def _on_load_finished(self):
self.html = self.toHtml(self.Callable)
print('Load finished')
def Callable(self, html_str):
self.html = html_str
self.app.quit()
def main():
page = Page('https://www.cashpoint.com/de/fussball/deutschland/bundesliga')
soup = bs.BeautifulSoup(page.html, 'html.parser')
js_test = soup.find('div', class_='game__team game__team__football')
print(js_test.text)
if __name__ == '__main__': main()
但这不适用于我试图抓取的 网站。我得到一个 AttributeError: 'NoneType' object has no attribute 'text' 错误。虽然在上面的文章中有一个为动态加载的网站写的方法,但是我并没有通过这个方法得到网站的内容。正如我所读到的,处理动态加载的 网站 的第一种方法是确定如何在页面上呈现数据。我该怎么办?为什么 PyQt5 不能在那个 网站 上工作? Selenium 方式对我来说不是一个选择,因为它太慢而无法获得实时赔率。当我检查 网站 使用的 HTML 内容,然后使用 Beautifulsoup 或 Scrapy 的常规方法时,是否可以获得该 网站 的 HTML 内容?提前谢谢你。
解决方案
提供的代码失败,因为即使页面已完成加载,新创建的元素(例如 div)也是异步创建的,例如你想得到 "game__team" 和 "game__team__football",所以当 loadFinished 发出信号时,即使没有创建这些元素也是一样的。
一种可能的解决方案是直接使用javascript通过runJavaScript()方法获取文本列表,如果列表为空,则在时间T重试,直到列表不为空。
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
class Scrapper(QtCore.QObject):
def __init__(self, interval=500, parent=None):
super().__init__(parent)
self._result = []
self._interval = interval
self.page = QtWebEngineWidgets.QWebEnginePage(self)
self.page.loadFinished.connect(self.on_load_finished)
self.page.load(
QtCore.QUrl("https://www.cashpoint.com/de/fussball/deutschland/bundesliga")
)
@property
def result(self):
return self._result
@property
def interval(self):
return self._interval
@interval.setter
def interval(self, interval):
self._interval = interval
@QtCore.pyqtSlot(bool)
def on_load_finished(self, ok):
if ok:
self.execute_javascript()
else:
QtCore.QCoreApplication.exit(-1)
def execute_javascript(self):
self.page.runJavaScript(
"""
function text_by_classname(classname){
var texts = [];
var elements = document.getElementsByClassName(classname);
for (const e of elements) {
texts.push(e.textContent);
}
return texts;
}
[].concat(text_by_classname("game__team"), text_by_classname("game__team__football"));
""",
self.javascript_callback,
)
def javascript_callback(self, result):
if result:
self._result = result
QtCore.QCoreApplication.quit()
else:
QtCore.QTimer.singleShot(self.interval, self.execute_javascript)
def main():
app = QtWidgets.QApplication(sys.argv)
scrapper = Scrapper(interval=1000)
app.exec_()
result = scrapper.result
del scrapper, app
print(result)
if __name__ == "__main__":
main()
输出:
[' 1899 Hoffenheim ', ' FC Augsburg ', ' Bayern München ', ' Werder Bremen ', ' Hertha BSC ', ' SC Freiburg ', ' 1. Fsv Mainz 05 ', ' Borussia Dortmund ', ' 1. FC Köln ', ' Bayer 04 Leverkusen ', ' SC Paderborn ', ' FC Union Berlin ', ' Fortuna Düsseldorf ', ' RB Leipzig ', ' VFL Wolfsburg ', ' Borussia Mönchengladbach ', ' FC Schalke 04 ', ' Eintracht Frankfurt ', ' Werder Bremen ', ' 1. Fsv Mainz 05 ', ' Borussia Dortmund ', ' RB Leipzig ', ' FC Augsburg ', ' Fortuna Düsseldorf ', ' FC Union Berlin ', ' 1899 Hoffenheim ', ' Bayer 04 Leverkusen ', ' Hertha BSC ', ' Borussia Mönchengladbach ', ' SC Paderborn ', ' VFL Wolfsburg ', ' FC Schalke 04 ', ' Eintracht Frankfurt ', ' 1. FC Köln ', ' SC Freiburg ', ' Bayern München ', ' 1899 Hoffenheim ', ' Borussia Dortmund ', ' Bayern München ', ' VFL Wolfsburg ', ' 1899 Hoffenheim ', ' Bayern München ', ' Hertha BSC ', ' 1. Fsv Mainz 05 ', ' 1. FC Köln ', ' SC Paderborn ', ' Fortuna Düsseldorf ', ' VFL Wolfsburg ', ' FC Schalke 04 ', ' Werder Bremen ', ' Borussia Dortmund ', ' FC Augsburg ', ' FC Union Berlin ', ' Bayer 04 Leverkusen ', ' Borussia Mönchengladbach ', ' VFL Wolfsburg ', ' Eintracht Frankfurt ', ' SC Freiburg ', ' 1899 Hoffenheim ', ' Bayern München ']