简介
scrapy作为爬虫利器,我就不多说了。
常见的结合js的爬虫,一般用来扒取网页动态内容,就是通过操作js获取渲染的内容。
现在大部分网站都是ajax+json获取数据的方式,所以,大家习惯性一上来爬虫,第一件事就是抓包,然后找规律抓数据。当然有时候,接口加密算法很复杂,短时间内很难破解,通过js抓取内容相对容易,这时候结合js的爬虫就能比较直接地达到目的,当然数据抓取效率不如直接抓接口来得快。
结合js的爬虫
目前,我知道的结合js的爬虫有以下3种。(有补充的,麻烦大神留言。)
- selenium+webdriver(如firefox,chrome等)。这要求你系统有对应浏览器,并且过程中要全程开浏览器。说白了,就是你通过浏览器能看到啥,就能抓到啥。一般遇到特别复杂的验证码时,这个方法是有必要的,当然,开着浏览器爬虫的效率可想而知。
- selenium+phantomjs。PhantomJS是一个WebKit,他的使用方法和webdriver一样,但是他不需要开浏览器,你可以直接跑在无需GUI的linux服务器上,这点很赞。
- scrapy-splash。这个和以上两种方法比,优势有以下几点。
- splash作为js渲染服务,是基于Twisted和QT开发的轻量浏览器引擎,并且提供直接的http api。快速、轻量的特点使其容易进行分布式开发。
- splash和scrapy融合,两种互相兼容彼此的特点,抓取效率较好。
- 虽然目前只有英文文档,但写的已经很详细了,仔细阅读便能快速开发。
本文主要介绍第三种爬虫方案的使用。
安装
关于安装,网上有很多了,请自行谷歌。
这里建议遵循官网安装方式。但注意因为splash服务需要依托docker。而docker在Ubuntu的安装方法,需要仔细看下文档,并注意Ubuntu版本。
启动
安装docker之后,官方文档给了docker启动splash容器的命令(docker run -d -p 8050:8050 scrapinghub/splash),但一定要查阅splash文档,来了解启动的相关参数。
比如我启动的时候,就需要指定max-timeout参数。因为我操作js时间较长时,很有可能超出默认timeout时间,以防万一我设定为3600(一小时),但对于本来js操作时间就不长的的同学,注意不要乱设定max-timeout。
docker run -d -p 8050:8050 scrapinghub/splash --max-timeout 3600
使用
关于scrapy-splash的使用教程主要来自scrapy-splash github和splash官方文档。除此之外,给出我最近写的一个scrapy-splash的代码。该代码主要实现js页面不断切换,然后抓取数据,下面是该代码的核心部分。因为,splash使用lua脚本实现js的操作,看下官方文档和这个代码,基本可以入门splash了。
fly_spider.py
class FlySpider(scrapy.Spider):
name = "FlySpider"
house_pc_index_url='xxxxx'
def __init__(self):
client = MongoClient("mongodb://name:pwd@localhost:27017/myspace")
db = client.myspace
self.fly = db["fly"]
def start_requests(self):
for x in xrange(0,1):
try:
script = """
function process_one(splash)
splash:runjs("$('#next_title').click()")
splash:wait(1)
local content=splash:evaljs("$('.scrollbar_content').html()")
return content
end
function process_mul(splash,totalPageNum)
local res={}
for i=1,totalPageNum,1 do
res[i]=process_one(splash)
end
return res
end
function main(splash)
splash.resource_timeout = 1800
local tmp=splash:get_cookies()
splash:add_cookie('PHPSESSID', splash.args.cookies['PHPSESSID'],"/", "www.feizhiyi.com")
splash:add_cookie('FEIZHIYI_LOGGED_USER', splash.args.cookies['FEIZHIYI_LOGGED_USER'],"/", "www.feizhiyi.com" )
splash:autoload("http://cdn.bootcss.com/jquery/2.2.3/jquery.min.js")
assert(splash:go{
splash.args.url,
http_method=splash.args.http_method,
headers=splash.args.headers,
})
assert(splash:wait(splash.args.wait) )
return {res=process_mul(splash,100)}
end
"""
agent = random.choice(agents)
print "------cookie---------"
headers={
"User-Agent":agent,
"Referer":"xxxxxxx",
}
splash_args = {
'wait': 3,
"http_method":"GET",
# "images":0,
"timeout":1800,
"render_all":1,
"headers":headers,
'lua_source': script,
"cookies":cookies,
# "proxy":"http://101.200.153.236:8123",
}
yield SplashRequest(self.house_pc_index_url, self.parse_result, endpoint='execute',args=splash_args,dont_filter=True)
# +"&page="+str(x+1)
except Exception, e:
print e.__doc__
print e.message
pass
如果想更深地利用scrapy-splash,请研究splash官方文档,另外,欢迎留言交流学习。
网友评论
Error downloading <POST http://192.168.99.100:8050/render.html>
...
twisted.web_newclient.ResponseNeverReceived: [<twisted.python.failure.Failure twisted.internet.error.ConnectionLost: Connection to the other side was lost in a non-clean fashion.>]
相关部分代码如下:
def start_requests(self): for url in self.start_urls: yield scrapy.Request(url, self.parse, meta={ 'splash': { 'endpoint': 'render.html', 'args': {'wait': 0.5} } })
请问有解决方法么?