抓取动态网页(如何从javascript页面爬取信息中进行数据爬取?(一))

优采云 发布时间: 2021-09-17 21:00

  抓取动态网页(如何从javascript页面爬取信息中进行数据爬取?(一))

  一、simple动态页面爬行

  我们以前的页面爬行工作是基于静态页面的。但是现在很多页面使用动态页面,其中70%的动态页面是由JavaScript编写的。因此,了解如何从JavaScript页面抓取信息对我们来说非常重要

  在了解具体情况之前,我们需要了解AJAX是什么。它的英文全称是AsynchronousJavaScript和XML,它是一种异步JavaScript和XML。我们可以通过Ajax请求页面数据,返回的数据格式是JSON类型

  然后我们可以根据页面的Ajax格式抓取数据。下面是一个简单的页面爬网

  import json

from Chapter3 import download

import csv

def simpletest():

'''

it will write the date to the country.csv

the json data has the attribute records, and the records has area, country and capital value

:return:

'''

fileds = ('area', 'country', 'capital')

writer = csv.writer(open("country.csv", "w"))

writer.writerow(fileds)

d = download.Downloader()

html = d("http://example.webscraping.com/ajax/search.json?page=0&page_size=10&search_term=A")

try:

ajax = json.loads(html)

except Exception as e:

print str(e)

else:

for record in ajax['records']:

row = [record[filed] for filed in fileds]

writer.writerow(row)

if __name__ == "__main__":

simpletest()

  我不知道这是否是问题所在。现在我无法从上述网站下载数据。执行上述程序。以下是结果图:

  

  二、呈现动态页面

  在开始之前,首先下载pyside并直接使用PIP install pyside命令行

  然后我们可以使用pyside来抓取数据

  from PySide.QtWebKit import *

from PySide.QtGui import *

from PySide.QtCore import *

import lxml.html

def simpletest():

'''

get content of the div # result in http://example.webscraping.com/places/default/dynamic

:return: content

'''

app = QApplication([])

webview = QWebView()

loop = QEventLoop()

# finish the loop if we have finished load the html

webview.loadFinished.connect(loop.quit)

webview.load(QUrl("http://example.webscraping.com/places/default/dynamic"))

loop.exec_()

htmled = webview.page().mainFrame().toHtml()

# get the special content

tree = lxml.html.fromstring(htmled)

return tree.cssselect('#result')[0].text_content()

content = simpletest()

print content

  我们回顾了简单动态页面爬行的内容。以前的方法不成功。我认为主要原因是我的网站写得不正确,所以在学习pyside之后,我们可以使用这种新方法进行数据爬行。以下是具体代码:

  def getallcountry():

'''

open the html and set search term = a and page_size = 10

and then click auto by javascript

:return:

'''

app = QApplication([])

webview = QWebView()

loop = QEventLoop()

# finish the loop if we have finished load the html

webview.loadFinished.connect(loop.quit)

webview.load(QUrl("http://example.webscraping.com/places/default/search"))

loop.exec_()

# show the webview

webview.show()

frame = webview.page().mainFrame()

# set search text is b

frame.findFirstElement('#search_term').setAttribute('value', 'b')

# set page_size is 10

frame.findFirstElement('#page_size option:checked').setPlainText('10')

# click search button auto

frame.findFirstElement('#search').evaluateJavaScript('this.click()')

app.exec_()

  以下是结果图:

  

  在上面的过程中,我们只使用pyside在页面上获取结果,但还没有对数据进行爬网。因为Ajax在响应事件时有一定的延迟,所以有三种方法可以抓取数据:

  1、等待一定时间(效率低下)

  2、rewrite QT的网络管理器,以跟踪URL请求的完成时间(不适用于客户端问题的情况)

  3、轮询页面并等待特定内容出现(检查时浪费CPU时间)

  一般来说,第三种方法更可靠、更方便。下面是它的概念代码:它的主要思想是while循环。如果找不到元素,请继续尝试

  

  为了使上述方法更通用,我们可以将它们编写在一个类中。此类收录以下功能:下载、获取HTML、查找对应元素、设置属性值、设置文本值、单击、轮询页面并等待下载

<p>from PySide.QtCore import *

from PySide.QtGui import *

from PySide.QtWebKit import *

import time

import sys

class BrowserRender(QWebView):

def __init__(self, show=True):

'''

if the show is true then we can see webview

:param show:

'''

self.app = QApplication(sys.argv)

QWebView.__init__(self)

if show:

self.show()

def download(self, url, timeout=60):

'''

download the url if timeout is false

:param url: the download url

:param timeout: the timeout time

:return: html if not timeout

'''

loop = QEventLoop()

timer = QTimer()

timer.setSingleShot(True)

timer.timeout.connect(loop.quit)

self.loadFinished.connect(loop.quit)

self.load(QUrl(url))

timer.start(timeout*1000)

loop.exec_()

if timer.isActive():

timer.stop()

return self.html()

else:

print "Request time out "+url

def html(self):

'''

shortcut to return the current html

:return:

'''

return self.page().mainFrame().toHtml()

def find(self, pattern):

'''

find all elements that match the pattern

:param pattern:

:return:

'''

return self.page().mainFrame().findAllElements(pattern)

def attr(self, pattern, name, value):

'''

set attribute for matching pattern

:param pattern:

:param name:

:param value:

:return:

'''

for e in self.find(pattern):

e.setAttribute(name, value)

def text(self, pattern, value):

'''

set plaintext for matching pattern

:param pattern:

:param value:

:return:

'''

for e in self.find(pattern):

e.setPlainText(value)

def click(self, pattern):

'''

click matching pattern

:param pattern:

:return:

'''

for e in self.find(pattern):

e.evaluateJavaScript("this.click()")

def wait_load(self, pattern, timeout=60):

'''

wait untill pattern is found and return matches

:param pattern:

:param timeout:

:return:

'''

deadtiem = time.time() + timeout

while time.time()

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线