python scrapy 的概念、安装、使用和案例

三十、python scrapy 的概念、安装、使用和案例

Scrapy介绍

ScrapyPython开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试

 

官网:http://scrapy.org

 

Scrapy安装

安装前所需安装:https://pypi.python.org  在官网汇中找

Lxml

Zope.interface

Twisted

Pywin32      -exe安装

pyOpenSSL    -whl安装

安装完上面的就尅安装:

Scrapy       - pip install scrapy(pip直接连上网安装即可;如用package方式安装得下载包)

 

安装好后验证一下:

Import scrapy  或者直接在命令窗口输入:scrapy

 

Scrapy的使用方式

1、交互式

在命令端输入 scrapy shell ‘url’

C:\Users\lyd>scrapy

C:\Users\lyd>scrapy shell "https://www.baidu.com"

运行上面的shell出错:

    import win32api

ImportError: No module named win32api

解决方法:

安装:pywin32-221.win-amd64-py2.7.exe   注意64位系统不要安装...win-32-py2.7.exe

>>> response

<200 https://www.baidu.com>

>>> response.xpath('//div')

Response对象:

-xpath()  xpath提取。主要讲这个

-css()  css选择器提取

-extract()  

-re()  用正则提取感兴趣内容

>>> exit()   退出

 

2、创建项目

Scrapy startproject projectname

E:\PycharmProjects\WebCrawler>scrapy startproject scrapy01   创建项目

3、创建splider 本质就是在工程的spider包中创建一个py文件,手动和命令创建都可以。

Scrapy genspider spider ‘starturl’

创建spider注意starturl可以创建后不对再更正

E:\PycharmProjects\WebCrawler>cd scrapy01

E:\PycharmProjects\WebCrawler\scrapy01>scrapy genspider DoubanSpider "https://ww

w.douban.com"

E:\PycharmProjects\WebCrawler\scrapy01>scrapy genspider SinaSpider "https://www.sina.com.cn"

代码1

====================DoubanSpiderSinaSpider类似如下================

class SinaspiderSpider(scrapy.Spider):

    name = 'SinaSpider'

    allowed_domains = ['www.sina.com.cn']

    start_urls = ['http://www.sina.com.cn/']    #可以修改,是一个列表

 

    def parse(self, response):

        print response.body

        print response.url

=============================================================================

 

4、运行爬虫

Scrapy crawl spidername

E:\PycharmProjects\WebCrawler\scrapy01>scrapy crawl DoubanSpider

E:\PycharmProjects\WebCrawler\scrapy01>scrapy crawl SinaSpider

 

5、pycharm中交互式运行创建的爬虫:

首先在scrapy01/scrapy01包下创建一个main.py文件;其次在里面编写:

fromscrapyimportcmdline
cmdline.execute('scrapy crawl SinaSpider'.split())

然后运行该文件即可;

 

 

项目的目录结构:


Scrapy的架构:

各个组件及在系统中发生的数据流的概览(绿色箭头所示)https://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/architecture.html

 

各个组件:

Scrapy Engine

引擎负责控制数据流在系统中所有组件中流动,并在相应动作发生时触发事件。详细内容查看下面的数据流(Data Flow)部分。

 

调度器(Scheduler)

调度器从引擎接受request并将他们入队,以便之后引擎请求他们时提供给引擎。

 

下载器(Downloader)

下载器负责获取页面数据并提供给引擎,而后提供给spider

 

Spiders

SpiderScrapy用户编写用于分析response并提取item(即获取到的item)或额外跟进的URL的类。 每个spider负责处理一个特定(或一些)网站。 更多内容请看 Spiders

 

Item Pipeline

Item Pipeline负责处理被spider提取出来的item。典型的处理有清理、 验证及持久化(例如存取到数据库中)。 更多内容查看Item Pipeline

流程:

1. 引擎打开一个网站(open a domain),找到处理该网站的Spider并向该spider请求第一个要爬取的URL(s)

2. 引擎从Spider中获取到第一个要爬取的URL并在调度器(Scheduler)Request调度。

引擎向调度器请求下一个要爬取的URL

3. 调度器返回下一个要爬取的URL给引擎,引擎将URL通过下载中间件(请求(request)方向)转发给下载器(Downloader)

4. 一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件(返回(response)方向)发送给引擎。

5. 引擎从下载器中接收到Response并通过Spider中间件(输入方向)发送给Spider处理。

6. Spider处理Response并返回爬取到的Item(跟进的)新的Request给引擎。

7. 引擎将(Spider返回的)爬取到的ItemItem Pipeline,将(Spider返回的)Request给调度器。

(从第二步)重复直到调度器中没有更多地request,引擎关闭该网站。

 

 scrapy项目实战

需求:

1. 爬取豆瓣图书频道top250   (爬虫脚本)

 https://book.douban.com/top250

2. 爬取目标  (items.py)

 图书名字、出版商、评分、热度                        

 内容简介

 精彩评论(课后练习)

3. 持久化   (pipelie.py)

 保存到mysqlmongdb数据库



将本项目分两步走:

一、先爬取基本信息,即一级页面,保存到本地的csv

1、构建项目,cmd中执行命令如下:E:\PycharmProjects\WebCrawler>scrapy startproject scrapydouban

2、在项目的根:scrapydouban下去创建创建main.py文件并设置以该脚本启动运行:

 


3、在项目下的settings.xml中添加如下:

#add settings of mine
#使用useragent代理,否则使用如下的默认值,显然是爬虫的agent,容易被阻止
USER_AGENT='Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36'
#保存文件路径和格式,无需手动创建
FEED_URI=u'file:///E:/pythondata/doubanbooks.csv'
FEED_FORMAT='CSV'
#关闭cookies,也是为阻止反爬虫
COOKIES_ENABLED=False

 

4、在项目下的items.py中添加如下:

fromscrapyimportItem,Field

class DoubanBookItem(Item):
    title = Field()
    title2 = Field()
    info = Field()
    rate = Field()
    hot = Field()

 

5、编写bookspider.py文件:

E:\PycharmProjects\WebCrawler\scrapydouban>scrapy genspider bookspider 'https://book.douban.com/top250'

添加内容如下:

fromscrapy.spidersimportBaseSpider
from scrapy.httpimportRequest
from scrapy.selectorimportSelector

#引入自己的模块很多种情况和方式,跨目录引入可以将项目跟目录(点击右键)标记为Mark Directory As Source Root。注意不同环境也不一样
import scrapydouban.itemsimportDoubanBookItem

class Books(BaseSpider):
    name = 'DoubanSpider'#需要和main.py中那个相同
    start_urls = ['https://book.douban.com/top250']
    defparse(self,response):
        item = DoubanBookItem()
        selector = Selector(response)
        books = selector.xpath('//td[@valign="top" and not(@width)]')
        foreachbookinbooks:
            title = eachbook.xpath('div[@class="pl2"]/a/text()').extract()[0]
            # title = title[0]
            title2 = eachbook.xpath('p[@class="quote"]/span/text()').extract()
            title2 = title2[0]iflen(title2) >0else''
            info = eachbook.xpath('p[@class="pl"]/text()').extract()[0]
            rate = eachbook.xpath('div[@class="star clearfix"]/span[@class="rating_nums"]/text()').extract()[0]
            hot = eachbook.xpath('div[@class="star clearfix"]/span[@class="pl""]/text()').extract()[0]
            #采用字典方式赋值
            item['title'] = title
            item['title2'] = title2
            item['info'] = info
            item['rate'] = rate
            item['hot'] = hot
            yielditem
        nextlink = selector.xpath('//span[@class="next"]/a/@href').extract()
        ifnextlink:
            nextlink = nextlink[0]
            yieldRequest(nextlink,callback=self.parse)

 

二、第二阶段,要抓取二级页面的评论。并将其持久化到mysqlmongodb

1、settings.xml文件中新增两行,使用上持久化的mysqlpiplinemongodbpipline

#多个时逗号分隔,是一个字典结构。key是包名.模块名.类名 ,值是其对应的优先顺序。范围为1-1000
ITEM_PIPELINES = {
    'scrapydouban.mongopipline.MongoDoubanBookPipline':300,
    'scrapydouban.mysqlpipline.MysqlDoubanBookPipline':400,
}

# mongo settings
MONGODB_SERVER = '192.168.216.7'
MONNGODB_PORT = 27017
MONNGODB_DB = 'qianfeng'
MONNGODB_COLLECTION = 'scrapy.doubanbook'

#设置爬虫时间间隔
DOWNLOAD_DELAY = 2
RANDOMIZE_DOWNLOAD_DELAY = True

 

2、将原来的items.py数据结构内容注释,新增数据结构如下:

classDoubanBookDetailItem(Item):
    title = Field()
    title2 = Field()
    info = Field()
    rate = Field()
    hot = Field()
    href = Field() #二级页面的评论的url
    intr = Field()#二级页面的剪短评论
    reviews = Field()#书的所有评论url的列表

 

3、scrapydouban包下创建两个管道文件,一个是mongopipline,另一个是mysqlpipline。代码分别如下:

fromscrapy.confimportsettings
from pymongoimportMongoClient
class MongoDoubanBookPipline(object):
    #初始化,获取mongo的连接信息
    def__init__(self):
        dbserver = settings['MONGODB_SERVER']
        dbport = settings['MONNGODB_PORT']
        dbname = settings['MONNGODB_DB']
        collname = settings['MONNGODB_COLLECTION']
        client = MongoClient(dbserver,dbport)
        db = client[dbname]
        self.col = db[collname]
    #根据自带生成的piplines.py我们知道这个方法必须实现
    defprocess_item(self,item,spider):
        book = dict(item)  #转成json
        self.col.insert(book)
        returnitem
    defclose_spider(self,spider):
        pass

 

importMySQLdb
class MysqlDoubanBookPipline(object):
    #初始化,获取mysql的连接信息
    def__init__(self):
        self.conn = MySQLdb.Connect(host='192.168.216.7',port=3306,user='root',passwd='root',db='testdb',charset='utf8')
        self.conn.autocommit(True)
        self.cursor =self.conn.cursor()
    #根据自带生成的piplines.py我们知道这个方法必须实现
    defprocess_item(self,item,spider):
        sql = 'insert into doubanbook(title,title2,rate,hot,intr,info) values(%s,%s,%s,%s,%s,%s)'
        bookinfo = [item['title'],item['title2'],item['rate'],item['hot'],item['intr'],item['info']]
        self.cursor.execute(sql,bookinfo)
        returnitem
    #爬虫结束出发一次
    defclose_spider(self,spider):
        self.cursor.close()
        self.conn.close()

 

 

4、在spiders包下面新增一个文件bookspider2.py,内容如下:

fromscrapy.spidersimportBaseSpider
from scrapy.httpimportRequest
from scrapy.selectorimportSelector
import scrapy
#引入自己的模块很多种情况和方式,跨目录引入可以将项目跟目录(点击右键)标记为Mark Directory As Source Root。注意不同环境也不一样
from scrapydouban.itemsimportDoubanBookDetailItem
from urlparseimporturljoin
from scrapy.utils.responseimportget_base_url
class Books(BaseSpider):
    name = 'DoubanBookDetailSpider'#需要和main.py中那个相同
    start_urls = ['https://book.douban.com/top250']
    defparse(self,response):
        item= DoubanBookDetailItem()#注意此种方式极容易造成重复,因为回调时对象地址不变
        selector = Selector(response)
        books = selector.xpath('//td[@valign="top" and not(@width)]')
        foreachbookinbooks:
            title = eachbook.xpath('div[@class="pl2"]/a/text()').extract()[0].strip()
            # title = title[0]
            title2 = eachbook.xpath('p[@class="quote"]/span/text()').extract()
            title2 = title2[0]iflen(title2) >0else''
            info = eachbook.xpath('p[@class="pl"]/text()').extract()[0]
            rate = eachbook.xpath('div[@class="star clearfix"]/span[@class="rating_nums"]/text()').extract()[0]
            hot = eachbook.xpath('div[@class="star clearfix"]/span[@class="pl"]/text()').extract()[0]
            href = eachbook.xpath('div[@class="pl2"]/a/@href').extract()[0]#书的url
            #采用字典方式赋值
            # item['title'] = title
            # item['title2'] = title2
            # item['info'] = info
            # item['rate'] = rate
            # item['hot'] = hot
            # item['href'] = href
            # item['intr'] = '' #没有数据先给初始值
            # item['reviews'] = []
            # yield item
            print
            
#如果需要回调时,传过去的对象地址一样,所以会重复
            yieldRequest(url=href,callback=self.parse_bookdetail,dont_filter=False,
                                 meta={'item': DoubanBookDetailItem(title=title,title2=title2,info=info,
                                                                    rate=rate,hot=hot,href=href,intr='',reviews=[])})
        nextlink = selector.xpath('//span[@class="next"]/a/@href').extract()
        ifnextlink:
            nextlink = nextlink[0]
            yieldRequest(nextlink,callback=self.parse,dont_filter=False)

    defparse_bookdetail(self,response):
        selector = Selector(response)
        intrp = selector.xpath('//div[@class="related_info"]/div[@class="indent"]/div/div[@class="intro"]/p/text()').extract()
        iflen(intrp) >0:
            item = response.meta['item']#取出上一个方法存入的数据
            intr ='\r\n'.join(intrp)#将intr数组中的每一段都拼接上换行符
            item['intr'] = intr.lstrip().rstrip()
            yielditem

 

5、修改main.py中的运行spiderName:

fromscrapyimportcmdline
cmdline.execute('scrapy crawl DoubanBookDetailSpider'.split())

 

三、第三阶段,将二级页面的评论也爬虫下来。

1、修改bookspider2.py文件,其实是修改一个方法和添加一个方法:

defparse_bookdetail(self,response):
    selector = Selector(response)
    intrp = selector.xpath('//div[@class="related_info"]/div[@class="indent"]/div/div[@class="intro"]/p/text()').extract()
    iflen(intrp) >0:
        item = response.meta['item']#取出上一个方法存入的数据
        intr ='\r\n'.join(intrp)#将intr数组中的每一段都拼接上换行符
        item['intr'] = intr.lstrip().rstrip()
        # yield item   #第二阶段使用的,如果还要继续抓取评论则需要注释#####

        baseurl = get_base_url(response)
        #https://book.douban.com/subject/1770782/reviews   评论的url是在书的超链接加reviews
        reviewurl = urljoin(baseurl,'reviews')
        print'reviewurl=====',reviewurl
        yieldRequest(url=reviewurl,meta={'item': item},callback=self.parse_bookreview)

def parse_bookreview(self,response):
    item = response.meta['item']
    selector = Selector(response)
    # reviews = selector.xpath('//div[@class="review-list"]/div[@xmlns:v="http://rdf.data-vocabulary.org/#"]/div[@class="main review-item"]/div[@class="main-bd"]/div[@class="review-short"]/div[@class="short-content"]/text()').extract()
    reviews = selector.xpath('//div[@class="short-content"]/text()').extract()
    printreviews
    ifreviews:
        item['reviews'].extend(reviews)
    nextlink = selector.xpath('//span[@class="next"]/a/@href').extract()
    ifnextlink:
        nextlink = nextlink[0]
        yieldscrapy.Request(nextlink,callback=self.parse_obokreview,meta={'item':item})
    else:
        yielditem

 

然后测试即可。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据东哥(Aidon)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值