[英]Parsing html from a javascript rendered url with python object
我想從以下網址及其所有后續頁面中提取市場信息:
https://uk.reuters.com/investing/markets/index/.FTSE?sortBy=&sortDir=&pn=1
我已經使用以下網址中的一些代碼成功解析了我想要從首頁獲得的數據:
https://impythonist.wordpress.com/2015/01/06/ultimate-guide-for-scraping-javascript-rendered-web-pages
我還能夠解析出下一頁的URL,以使其進入循環,以便從下一頁獲取數據。 問題是由於我不完全了解的原因,它在下一頁加載之前崩潰了。
我有一種預感,就是我從“ impythonist”那里借來的課程可能導致了問題。 我不知道足夠的面向對象的程序來解決這個問題。 這是我的代碼,其中大部分是從上面的網址借來的:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
from lxml import html
import re
from bs4 import BeautifulSoup
class Render(QWebPage):
def __init__(self, url):
self.app = QApplication(sys.argv)
QWebPage.__init__(self)
self.loadFinished.connect(self._loadFinished)
self.mainFrame().load(QUrl(url))
self.app.exec_()
def _loadFinished(self, result):
self.frame = self.mainFrame()
self.app.quit()
base_url='https://uk.reuters.com'
complete_next_page='https://uk.reuters.com/investing/markets/index/.FTSE?sortBy=&sortDir=&pn=1'
#LOOP TO RENDER PAGES AND GRAB DATA
while complete_next_page != '':
print ('NEXT PAGE: ',complete_next_page, '\n')
r = Render(complete_next_page) # USE THE CLASS TO RENDER JAVASCRIPT FROM PAGE
result = r.frame.toHtml() # ERROR IS THROWN HERE ON 2nd PAGE
# PARSE THE HTML
soup = BeautifulSoup(result, 'lxml')
row_data=soup.find('div', attrs={'class':'column1 gridPanel grid8'})
print (len(row_data))
# PARSE ALL ROW DATA
stripe_rows=row_data.findAll('tr', attrs={'class':'stripe'})
non_stripe_rows=row_data.findAll('tr', attrs={'class':''})
print (len(stripe_rows))
print (len(non_stripe_rows))
# PARSE SPECIFIC ROW DATA FROM INDEX COMPONENTS
#non_stripe_rows: from 4 to 18 (inclusive) contain data
#stripe_rows: from 2 to 16 (inclusive) contain data
i=2
while i < len(stripe_rows):
print('CURRENT LINE IS: ',str(i))
print(stripe_rows[i])
print('###############################################')
print(non_stripe_rows[i+2])
print('\n')
i+=1
#GETS LINK TO NEXT PAGE
next_page=str(soup.find('div', attrs={'class':'pageNavigation'}).find('li', attrs={'class':'next'}).find('a')['href']) #GETS LINK TO NEXT PAGE WORKS
complete_next_page=base_url+next_page
我已經注釋了一些我已經編寫並理解的代碼,但是我真的不知道'Render'類中發生了什么足以診斷錯誤? 除非有別的東西?
這是錯誤:
result = r.frame.toHtml()
AttributeError: 'Render' object has no attribute 'frame'
解析完這些信息后,我不需要將其保留在類中,因此我想也許可以將其清除或重置,然后進行更新以保存第2頁:n中的新url信息,但是我不知道如何去做這個?
或者,如果有人知道從此頁面以及隨后的頁面中獲取此特定數據的另一種方法,那將同樣有用嗎?
提前謝謝了。
如何使用Selenium和phantomjs代替PyQt。
您可以通過執行“ pip install selenium”輕松獲得硒。 如果使用Mac,則可以通過執行“ brew install phantomjs”來獲取phantomjs。 如果您的PC是Windows,請使用choco而非brew,或Ubuntu使用apt-get。
from selenium import webdriver
from bs4 import BeautifulSoup
base_url = "https://uk.reuters.com"
first_page = "/business/markets/index/.FTSE?sortBy=&sortDir=&pn=1"
browser = webdriver.PhantomJS()
# PARSE THE HTML
browser.get(base_url + first_page)
soup = BeautifulSoup(browser.page_source, "lxml")
row_data = soup.find('div', attrs={'class':'column1 gridPanel grid8'})
# PARSE ALL ROW DATA
stripe_rows = row_data.findAll('tr', attrs={'class':'stripe'})
non_stripe_rows = row_data.findAll('tr', attrs={'class':''})
print(len(stripe_rows), len(non_stripe_rows))
# GO TO THE NEXT PAGE
next_button = soup.find("li", attrs={"class":"next"})
while next_button:
next_page = next_button.find("a")["href"]
browser.get(base_url + next_page)
soup = BeautifulSoup(browser.page_source, "lxml")
row_data = soup.find('div', attrs={'class':'column1 gridPanel grid8'})
stripe_rows = row_data.findAll('tr', attrs={'class':'stripe'})
non_stripe_rows = row_data.findAll('tr', attrs={'class':''})
print(len(stripe_rows), len(non_stripe_rows))
next_button = soup.find("li", attrs={"class":"next"})
# DONT FORGET THIS!!
browser.quit()
我知道上面的代碼效率不高(我覺得太慢了),但是我認為它將為您帶來所需的結果。 此外,如果您要抓取的網頁未使用Javascript,則甚至不需要PhantomJS和硒。 您可以使用請求模塊。 但是,由於我想向您展示與PyQt的對比,因此我在此答案中使用了PhantomJS和Selenium。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.