Scapy框架相关的内容,这里不在搬砖,官方给出的中文文档,已经足够详尽清晰。

JAVA 爬取静态网页 java爬取js动态网页_ajax

Scrapy框架上手非常简单,跟着教程一步步走就可以了,爬取一些静态资源是毫无问题的,但现如今,大部分网站为了封禁爬虫,都会采取一些防爬策略,最典型的是通过ajax动态渲染界面,以爬取图片为例,网页用js加载图片使得scrapy.request url时获得的response中不暴露图片url,而是一大段js函数,为解决这个问题,可以结合使用Python scrapy-splash拓展包。

1. 爬取动态页面环境准备

1.1 安装scrapy-splash,终端直接运行

pip install scrapy-splash

1.2. 安装scrapy-splash服务

docker pull scrapinghub/splash

1.3. 启动一个splash服务容器,运行:

docker run -p 8050:8050 scrapinghub/splash

如有疑问,可直接参考scrapy-splash项目地址https://github.com/scrapy-plugins/scrapy-splash

1.4.splash服务有啥用呢? 尝试用浏览器访问http://localhost:8050 可以看到如下界面:

试着在右边输入框输入任意一个ajax动态网页,点击render me! 稍等片刻后,便会看到页面返回了splash渲染后的结果。

JAVA 爬取静态网页 java爬取js动态网页_scrapy-splash java_02

2. 配置你的scrapy项目

2.1 在项目settings.py里面添加如下配置:

SPLASH_URL = 'http://localhost:8050'
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware':725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
SPIDER_MIDDLEWARES = { 'scrapy_splash.SplashDeduplicateArgsMiddleware': 100, }
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

2.2 在项目爬虫文件中修改scrapy.Request为SplashRequest,这样Scrapy engine访问Url时SplashRequest直接把请求发给sracpy-splash服务端,sracpy-splash服务端成功访问url后将渲染后的结果返回给scrapy-engine,代码如下:

script = """
function main(splash, args)
assert(splash:go(args.url))
assert(splash:wait(args.wait))
return { html = splash:html(),}
end
"""
classExampleSpider(scrapy.Spider):
defstart_requests(self):
for url in self.start_urls:
yield SplashRequest(url=url, callback=self.parse, endpoint='execute',args={'lua_source': script, 'wait': 0.5})
defparse(self, response):
pass

注意这里的request是通过执行lua脚本转发的,当然你也可以通过手动在要访问的url外面封装一层,让splash服务直接访问封装后的url。

2.2 接下来的就是爬虫具体的业务了,例如你如果想爬取某个网站并将网站上的图片保存到本地,

首先需要在项目items.py文件中新建imagepipeline,如:

import scrapyfrom scrapy.exceptions
import DropItemfrom scrapy.pipelines.images
import ImagesPipelineclass
MyImagesPipeline(ImagesPipeline):
defget_media_requests(self, item, info):
for image_url in item['image_urls']:
# 注意这里一定要用 scrapy.Request访问图片url,不能用SplashRequest访问url,
# 因为scrapy框架引擎本身不能解析SplashResponse,需要重写部分方法。
yield scrapy.Request(image_url)
defitem_completed(self, results, item, info):
image_paths = [x['path'] for ok, x in results if ok]
ifnot image_paths:
raise DropItem("Item contains no images")
item['image_paths'] = image_paths
return item

同样在项目settings.py里面配置下载中间件相关的配置:

ITEM_PIPELINES = {'你的项目名称.pipelines.MyImagesPipeline': 300}

IMAGES_STORE = '你项目保存图片的目录/'IMAGES_EXPIRES = 90

你的爬虫里面也需要重写parse函数,及时yield出imageItem给下载中间件,自动下载图片,代码如下:

defparse(self, response):
list_imgs = response.xpath('//div[@class="text"]/p/img/@src').extract()
# xpath需要修改成目标网站中你想提取的内容,如图片url等
iflist_imgs:
item = ImageItem()
item['image_urls'] = list_imgs
yield item

OK, 完成以上工作,就可以运行你的爬虫了,尽情的爬取网站中的各种小姐姐吧(手动偷笑)!