0

我想从以下网址及其所有后续页面中提取市场信息:

https://uk.reuters.com/investing/markets/index/.FTSE?sortBy=&sortDir=&pn=1

我已经使用以下 url 中的一些代码成功地从第一页解析了我想要的数据:

https://impythonist.wordpress.com/2015/01/06/ultimate-guide-for-scraping-javascript-rendered-web-pages

我还能够解析出下一页的 url 以输入循环,以便从下一页获取数据。问题是它在下一页加载之前由于我不完全理解的原因而崩溃。

我有一种预感,我从“impythonist”那里借来的课程可能会导致问题。我不知道足够的面向对象编程来解决这个问题。这是我的代码,其中大部分是从上面的 url 借来的:

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

我已经注释了我编写和理解的代码位,但我真的不知道“渲染”类中发生了什么足以诊断错误?除非它是别的东西?

这是错误:

result = r.frame.toHtml()
AttributeError: 'Render' object has no attribute 'frame'

解析完信息后,我不需要将信息保留在课堂上,所以我想也许可以以某种方式清除或重置它,然后更新以保存第 2 页的新 url 信息:n 但我不知道如何去做这个?

或者,如果有人知道从该页面和以下页面获取此特定数据的另一种方法,那么这同样有帮助吗?

提前谢谢了。

4

1 回答 1

1

使用 selenium 和 phantomjs 代替 PyQt 怎么样?
您可以通过执行“pip install selenium”轻松获取 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 和 selenium 也是不必要的。您可以使用请求模块。但是,由于我想向您展示与 PyQt 的对比,因此我在此答案中使用了 PhantomJS 和 Selenium。

于 2017-11-26T12:54:39.697 回答