pyspider框架介绍
pyspider 是个强大的由python实现的爬虫系统。
纯python的
强大的webui,支持脚本编辑,任务监控,项目管理和pyspider 是个强大的由python实现的爬虫系统。结果查看
消息队列支持,RabbitMQ,Beanstalk,Redis以及Kombu
支持任务优先级,定时,失败重试等调度方案
分布式架构,抓取js页面
支持Python2和3
pyspider框架安装
ubuntu
如果使用ubuntu
,请先运行sudo apt update
再运行sudo apt upgrade
更新
apt-get install python python-dev python-distribute python-pip \
libcurl4-openssl-dev libxml2-dev libxslt1-dev python-lxml \
libssl-dev zlib1g-dev
删除wsgidav
然后重新安装2.4.1
版本
windows
https://www.lfd.uci.edu/~gohlke/pythonlibs/ 中下载pycurl
安装
windows 下安装成功,运行报如下错误:
Deprecated option 'domaincontroller': use 'http_authenticator.domain_controller' instead.
解决方案:
删除wsgidav
然后重新安装2.4.1
版本
pypsider入门
安装好pyspider
后,创建一个项目文件夹用来存放相关文件,进入文件夹后运行pyspider
命令,默认情况下会运行一个web服务端监听5000端口,通过http://localhost:5000
即可访问pyspider的web管理界面,它看起来是这样的:
一期工程有5个状态:TODO,STOP,CHECKING,DEBUG和RUNNING
TODO - 创建一个脚本来编写
STOP- 您可以将项目标记为STOP您希望它停止(= =)。
CHECKING- 修改正在运行的项目时,为防止不完整修改,项目状态将CHECKING自动设置。
DEBUG/ RUNNING- 这两种状态对蜘蛛没有区别。但是将它标记为DEBUG第一次运行然后将其更改RUNNING为检查后是很好的。
抓取速度被控制,rate并burst用令牌桶算法。
rate - 一秒钟内有多少请求
burst- 考虑到这种情况,rate/burst = 0.1/3这意味着蜘蛛每10秒抓一页。所有任务都已完成,项目每分钟检查最后更新的项目。假设找到3个新项目,pyspider将“爆发”并抓取3个任务而不等待3 * 10秒。但是,第四项任务需要等待10秒。
要删除项目,请设置group为delete和状态STOP,等待24小时。
爬取目标(链家网)
因为我身处东莞,所以爬取的是东莞的
https://dg.lianjia.com/ershoufang/
新建项目
进入到了开发界面
def on_start(selef)
是脚本的入口。当你点击run
按钮时,它会被调用。self.crawl(url, callback=self.index_page)
是最重要的接口。它会添加一个新的待爬取任务。大部分的设置可以通过self.crawl
的参数去指定。def index_page(self, response)
接收一个response对象。response.doc
是一个pyquery
对象,它有一个类似jQuery
选择器一样的接口,去解析页面元素。def detail_page(self, response)
返回一个字典结果。这个结果默认会被写入resultdb
(结果数据库)。你可以通过复写on_result(self, result)
方法来按照你自己的需求处理结果。@every(minutes=24 * 60)
这个装饰器会告诉调度器,on_start
方法将会每天被调用。@config(age=10 * 24 * 60 * 60)
指定当self.crawl
爬取的页面类型为index_page
(当callback=self.index_page
)时的age参数的默认值。参数age
可以通过self.crawl(url, age=102460*60)
和crawl_config
来指定,直接在方法参数中指定具有最高的优先级。age=102460*60
告诉调度器抛弃10天内爬取过的请求。默认情况下,相同URL不会被爬取两次,甚至你修改了代码。对于初学者来说,第一次运行项目然后修改它,在第二次运行项目的情况非常常见,但是它不会再次爬行(阅读itag
了解解决方案)@config(priority=2)
标志着,detail page
将会被优先爬取。
你可以通过点击绿色的run
按钮,一步一步的调试你的脚本。切换到follows
面板,点击play
按钮前进。
注意点 :
在使用
self.crawl
函数时必须加上validate_cert=False
保证能够爬取https,不然会报599,SSL 错误解决办法想要爬取js生成的东西,需要使用
PhantomJS
,下载PhantomJS.exe
丢掉·python.exe
同路径下,通过添加参数fetch_type='js'
来启用此功能self.crawl
由于链家网没有使用js生成数据,所以没有加上fetch_type='js'
,当我运行,得到了链家网首页 364条a标签的链接
获取需要url所在的xpath路径
在重新crawl方法,我们可以看出title和url的输出,说明没有问题
对于pyspider还有一个简介的方法就是通过css选择器来获取对应的css路径,从下面可以看出代码没有问题
入库
对于入库需要写on_result
方法和初始化方法具体如下
不到半分钟,数据爬取完毕
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2019-07-21 17:08:14
# Project: lianjia
from pyspider.libs.base_handler import *
from lxml import etree
import pymysql
class Handler(BaseHandler):
crawl_config = {
}
def __init__(self):
db_config = {
'host': '', #ip
'user': '', #账号:不能用root的账号
'password': '',
'db': '',
'charset': 'utf8',
'port': 3306
}
self.db = pymysql.connect(**db_config)
self.cur = self.db.cursor()
# 创建表items
sql1 = 'create table if not exists items (url varchar(255) NOT NULL ,title VARCHAR(255) NOT NULL, price VARCHAR(255) NOT NULL, content mediumblob NOT NULL, Introduce mediumblob NOT NULL) '
self.cur.execute(sql1)
print('数据库创建成功')
@every(minutes=24 * 60)
def on_start(self):
# 通过迭代来不断的访问新的链接
for i in range(1,101):
self.crawl('https://dg.lianjia.com/ershoufang/{}'.format(i), callback=self.index_page,validate_cert=False)
@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
xml = etree.HTML(response.text)
urls = xml.xpath('//ul[@class="sellListContent"]//li/a/@href')
# 获取每页的li中的url
print(urls) #列表
#for each in response.doc('a[href^="http"]').items():
#self.crawl(each.attr.href, callback=self.detail_page,validate_cert=False)
for url in urls:
self.crawl(url, callback=self.detail_page,validate_cert=False)
@config(priority=2)
def detail_page(self, response):
# 爬取对应的title,url, pricecontent和Introduce
return {
"url": response.url,
"title": response.doc('title').text(),
"price": str(response.doc('.price > .total').text()) + '万',
"content": response.doc('.base').text(),
"Introduce":response.doc('.baseattribute > .content').text()
}
@config(priority=2)
def on_result(self, result):
sql = 'insert into items(url,title,price,content,Introduce) values(%s, %s,%s,%s,%s)'
try:
if result['url']:
self.cur.execute(sql, (result['url'], result['title'],result['price'], result['content'],result['Introduce']))
except Exception as e:
self.db.rollback()
print(e)
else:
self.db.commit()
不到半分钟爬取了1146条数据,但是有的数据的重复的,应该用集合来去重
■ Over ■
最后,祝有所学习,有所成长
回复【1024】获取学习资料
转发,好看支持一下,感谢
你的转发,就是对我最大的支持