前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >爬虫篇| pyspider 爬取链家网(八)

爬虫篇| pyspider 爬取链家网(八)

作者头像
润森
发布2019-08-29 11:10:46
1.5K0
发布2019-08-29 11:10:46
举报
文章被收录于专栏:毛利学Python毛利学Python

pyspider框架介绍

pyspider 是个强大的由python实现的爬虫系统。

  • 纯python的
  • 强大的webui,支持脚本编辑,任务监控,项目管理和pyspider 是个强大的由python实现的爬虫系统。结果查看
  • 消息队列支持,RabbitMQ,Beanstalk,Redis以及Kombu
  • 支持任务优先级,定时,失败重试等调度方案
  • 分布式架构,抓取js页面
  • 支持Python2和3
pyspider框架安装
  • ubuntu

如果使用ubuntu,请先运行sudo apt update 再运行sudo apt upgrade 更新

代码语言:javascript
复制
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 下安装成功,运行报如下错误:

代码语言:javascript
复制
 Deprecated option 'domaincontroller': use 'http_authenticator.domain_controller' instead.

解决方案:

删除wsgidav 然后重新安装2.4.1版本

pypsider入门

安装好pyspider后,创建一个项目文件夹用来存放相关文件,进入文件夹后运行pyspider命令,默认情况下会运行一个web服务端监听5000端口,通过http://localhost:5000即可访问pyspider的web管理界面,它看起来是这样的:

项目是独立的,但您可以将另一个项目作为模块导入 from projects import other_project 一期工程有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方法和初始化方法具体如下

不到半分钟,数据爬取完毕

代码语言:javascript
复制
#!/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条数据,但是有的数据的重复的,应该用集合来去重

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小刘IT教程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • pyspider框架安装
  • pypsider入门
  • 爬取目标(链家网)
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档