30.splash多页抓取--用js点击实现翻页

准备工作:

先在终端重启下docker服务:

sudo service docker start

然后让Docker容器以守护态运行,这样在中断远程服务器连接后,不会终止Splash服务的运行。

docker run -d -p 8050:8050 scrapinghub/splash

把要爬的网站先输进去,点下render,让splash开始渲染。



如果像上图这样,那也不必执行爬虫操作,浏览器都无法渲染,python还操作个锤子。
-_-!
可能是网络不太好,再点一下,如果还是这样婶,就重启下网络

service network restart

重启网络后再点一下,看是否OK。如果还是不行,就执行下重启电脑这个大杀器。
为什么说重启电脑是大杀器呢?因为重启电脑后真的是可以加载了:


正式开始:

既然是要爬取多页,那就先定位下翻页的元素,如下图所示,点向右的箭头可以控制翻页,那就定位该元素,写出个css选择器出来。也可以让浏览器给copy,但这家伙copy出来的东西有时候不太准确,还需要自己加以判断。



有了这个元素写一点js代码就OK了。

# 模拟点击采用js的方式
script = """
function main(splash, args)
  splash.images_enabled = false  
  assert(splash:go(args.url))
  assert(splash:wait(1))
  js = string.format("document.querySelector('div.paginationjs-pages > ul > li.paginationjs-next.J-paginationjs-next a').click();", args.page)
  splash:runjs(js)
  assert(splash:wait(5))
  return splash:html()
end
"""

上面代码的意思,很显然嘛,这里不做过多介绍。
好了好了,说一哈:
1.images_enabled = false不加载图片,因为加载图片会让网页加载变慢,默认是加载的,需要设置false,才是不加载;
2.go(),请求链接;
3.wait(),相当于python中的sleep;
4.js中的代码在本篇中表示定位到翻页的那个右箭头,然后点击一下,后面跟着的args.page至关重要,如果没有它,就无法实现翻页,这里它是一个伏笔,等待下面的代码调用;
5.runjs(),执行上面的JavaScript代码;
6.html(),返回html源代码。

然后start_requests长这个样子:

def start_requests(self):
    for page in range(1, 5):
        url = self.base_url
        yield SplashRequest(url, callback=self.parse, endpoint='execute',
                            args={'lua_source': script, 'page': page, 'wait': 10})

完整代码如下:

# -*- coding: utf-8 -*-
import scrapy
from scrapy_splash import SplashRequest
from caigou.items import CaigouItem

# 模拟点击采用js的方式
script = """
function main(splash, args)
  splash.images_enabled = false  
  assert(splash:go(args.url))
  assert(splash:wait(1))
  js = string.format("document.querySelector('div.paginationjs-pages > ul > li.paginationjs-next.J-paginationjs-next a').click();", args.page)
  splash:runjs(js)
  assert(splash:wait(5))
  return splash:html()
end
"""


class ZfcaigouSpider(scrapy.Spider):
    name = 'zfcaigou'
    allowed_domains = ['www.zjzfcg.gov.cn']
    base_url = 'http://www.zjzfcg.gov.cn/purchaseNotice/index.html?categoryId=3001'

    def start_requests(self):
        for page in range(1, 5):
            url = self.base_url
            yield SplashRequest(url, callback=self.parse, endpoint='execute',
                                args={'lua_source': script, 'page': page, 'wait': 10})

    def parse(self, response):
        # print(response.body.decode("utf-8"))
        infodata = response.css(".items p")
        for infoline in infodata:
            caigouitem = CaigouItem()
            caigouitem['city'] = infoline.css(".warning::text").extract()[0].replace("[", "").replace("·", "").strip()
            caigouitem['issuescate'] = infoline.css(".warning .limit::text").extract()[0]
            caigouitem['title'] = infoline.css("a .underline::text").extract()[0].replace("]", "")
            caigouitem['publish_date'] = infoline.css(".time::text").extract()[0].replace("[", "").replace("]", "")
            yield caigouitem

爬取结果:

因为自定义只爬5页,有60个数据,说明爬成功了,开心,嘻嘻。

注:
wait()

在脚本内调用的wait()方法类似于Python中的sleep(),其参数为等待的秒数。当Splash执行到此方法时,它会转而去处理其他任务,然后在指定的时间过后再回来继续处理。

main()

main()方法的第一个参数是splash,这个对象非常重要,它类似于Selenium中的WebDriver对象,我们可以调用它的一些属性和方法来控制加载过程。接下来,先看下它的属性。

args

该属性可以获取加载时配置的参数,比如URL,如果为GET请求,它还可以获取GET请求参数;如果为POST请求,它可以获取表单提交的数据。Splash也支持使用第二个参数直接作为args

images_enabled

此属性可以设置图片是否加载,默认情况下是加载的。禁用该属性后,可以节省网络流量并提高网页加载速度。但是需要注意的是,禁用图片加载可能会影响JavaScript渲染。因为禁用图片之后,它的外层DOM节点的高度会受影响,进而影响DOM节点的位置。因此,如果JavaScript对图片节点有操作的话,其执行就会受到影响。
另外值得注意的是,Splash使用了缓存。如果一开始加载出来了网页图片,然后禁用了图片加载,再重新加载页面,之前加载好的图片可能还会显示出来,这时直接重启Splash即可。

go()

该方法用来请求某个链接,而且它可以模拟GET和POST请求,同时支持传入请求头、表单等数据

runjs()

此方法可以执行JavaScript代码,它与evaljs()的功能类似,但是更偏向于执行某些动作或声明某些方法。

完整项目请参考:https://github.com/hfxjd9527/caigou

你可能感兴趣的:(30.splash多页抓取--用js点击实现翻页)