为了账号安全,请及时绑定邮箱和手机立即绑定

Scrapy初体验

标签:
Python

学了python之后一直在给自己找点儿什么需求练练手,爬虫是学python最快的途径,就想着爬点豆瓣电影的数据吧,在经过了一系列重复造轮子之后,决定体验一下scrapy。

scrapy的架构图:

webp

scrapy_architecture.png

1、引擎(ScrapyEngine): 用来处理整个系统的通讯,数据流处理, 触发事务(框架核心)。
2、调度器(Scheduler): 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址。
3、下载器(Downloader): 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)。
4、爬虫(Spiders): 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面。
5、项目管道(Pipeline): 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
6、下载器中间件(Downloader Middlewares): 位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
7、爬虫中间件(Spider Middlewares): 介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
8、调度中间件(Scheduler Middewares): 介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应

scrapy流程:

1.Spider将初始url告诉Engine,Engine将url添加到调度器的请求队列中
2.Engine从调度器队列中拿到下一个要请求的url,交给下载器(下载器中间件可以设置代理之类。。),下载器下载网页内容,交还给引擎
3.Engine将从下载器拿到的网页内容,交给spider,spider爬取所需要的内容,生成item交还给Engine,如果需要继续爬取,将新的url告诉Engine,并添加到调度器的请求队列中
4.pipeline 从Engine拿到爬取的实体进行处理

python&scrapy安装:

windows下安装python+scrapy

开始

创建项目:

scrapy startproject 项目名称

目录介绍:

.cfg         项目配置文件  定义了项目配置文件路径,部署信息等内容items.py     定义item数据结构的地方settings.py  项目的设置文件,定义项目的全局设置

生成spiders文件:

在spiders目录中进入命令行输入  scrapy genspider 爬虫名 要爬取的域名

刷新项目文件目录

spider文件中:
    name : 爬虫的名称
    start_urls : 为初始爬虫目录,就是第一次爬取的地址url

执行爬虫文件 :

scrapy crawl 爬虫名称

爬取豆瓣电影网站内容

在项目磁盘目录下打开命令行输入

scrapy startproject douban_demo

生成项目文件

修改settings.py文件中USER_AGENT和ROBOTSTXT_OBEY:不然请求会被拦截

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'ROBOTSTXT_OBEY = False

在spiders目录中进入命令行输入

scrapy genspider douban_spider movie.douban.com

之后会在spiders目录中生成一个douban_spider.py 的文件,修改start_urls:

start_urls = ['http://movie.douban.com/top250']

打开页面,我们接下来要抓取这些数据

webp

douban.png

在items.py中创建我们的数据模型:

class DouBanItem(scrapy.Item):
    #电影编号
    movie_num = scrapy.Field()    #电影封面地址
    movie_imgurl = scrapy.Field()    #电影名称
    movie_name = scrapy.Field()    #电影参与人员
    movie_person = scrapy.Field()    #电影评分
    movie_grade = scrapy.Field()    #电影口号
    movie_slogen = scrapy.Field()

douban_spider.py中 的 parse方法,就是我们写爬虫代码的地方

检查页面,查看页面标签详情,可以看到页面的标签结构

爬取数据:

movies = response.css('div.item')for movie in movies:
    movie_num = movie.css('em::text').extract_first()
    movie_imgurl = movie.css('img::attr(src)').extract_first()
    movie_name = movie.css('.title::text').extract_first()
    movie_person = movie.css('.bd p::text').extract_first()
    movie_grade = movie.css('.rating_num::text').extract_first()
    movie_slogen = movie.css('.inq::text').extract_first()

    doubanItem = DouBanItem()
    doubanItem['movie_num'] = movie_num
    doubanItem['movie_imgurl'] = movie_imgurl
    doubanItem['movie_name'] = movie_name
    doubanItem['movie_person'] = movie_person
    doubanItem['movie_grade'] = movie_grade
    doubanItem['movie_slogen'] = movie_slogen

将爬取到的数据加入pipline管道

yield doubanItem

将数据写入txt文本文件

with open('movie_info.txt','a+',encoding='utf-8') as f:
    f.write(movie_num+" : "+movie_name+" : \t"+movie_grade+"\n")
    f.write('封面图片地址 : '+movie_imgurl+'\n')
    f.write('参与人员 : '+movie_person+'\n')
    f.write(movie_slogen+"\n")
    f.write('\n-----------------------------------------\n')

    使用a+追加方式,编码使用utf-8,打开文本文件,往里写入

继续爬取下一页数据:

next_page = response.css('span.next a::attr(href)').extract_first()if next_page is not None:
    realUrl = "http://movie.douban.com/top250"+next_page
    realUrl = response.urljoin(realUrl)    yield scrapy.Request(realUrl,callback=self.parse)

根据css找到下一页按钮中的地址,这个页面是需要拼接host地址,如果 is not None 表示还有下一页,
urljoin(url)将地址添加到调度器请求队列中,scrapy.Request(realUrl,callback=self.parse)之情请求,设置回调使用当前parse方法作为返回数据的处理方法

用爬取到的数据,生成json文件

在命令行中(可以使用pycharm中的Terminal命令行)执行爬虫文件

scrapy crawl douban_spider -o douban.json'douban_spider'是douban_spider.py中name字段的值

执行完本地就会生成一个json文件

用爬取到的数据,生成csv格式文件

在命令行中(可以使用pycharm中的Terminal命令行)执行爬虫文件

scrapy crawl douban_spider -o douban.csv'douban_spider'是douban_spider.py中name字段的值

执行完本地就会生成一个csv文件

爬取数据存储MongoDB

首先在settings.py文件中打开 pipeline开关,并在最后面配置mongodb

ITEM_PIPELINES = {  'scrapy_demo.pipelines.ScrapyDemoPipeline': 300,
}
mongo_host = '127.0.0.1'mongo_port = 27017
mongo_db_name = 'douban'mongo_db_collection = 'douban_movie

在pipelines.py中编写代码
首先导入settings中的mongodb配置和mongodb

import pymongofrom scrapy_demo.settings import mongo_db_collection,mongo_db_name,mongo_host,mongo_port

在构造函数中传入配置参数:

def __init__(self):    # 端口号
    port = mongo_port    # 基地址
    host = mongo_host    # 数据库名
    dbname = mongo_db_name    # 表名
    sheetname = mongo_db_collection    # 创建client
    client = pymongo.MongoClient(host=host,port=port)    # 指定数据库
    mydb = client[dbname]    # 找到表
    self.post = mydb[sheetname]

在process_item方法中进行数据插入的编写

def process_item(self, item, spider):    # 将模型转化为字典
    data = dict(item)    # 将字典数据插入mongodb
    self.post.insert(data)    return item

运行之后就可以在数据库中看到咱们已经添加了数据

webp

0180912140030.png

对爬虫进行伪装

设置代理ip

为了不让要爬取的网站发现我们的爬取动作,需要对爬虫进行一些伪装,
我们可以通过下载器中间件(Downloader Middlewares)对我们的请求进行伪装

将settings.py中的DOWNLOADER_MIDDLEWARES配置打开(543为优先级,数字越小,优先级越高)

DOWNLOADER_MIDDLEWARES = {   'scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware': 543,
}

在middlewares.py文件中进行编写

创建一个中间件:

class DoubanProcess(object):
    def process_request(self,request,spider):
        request.meta['proxy'] = '你的代理ip地址'
        # 需要登录的话-因为加密需要byte类型,所以需要在前面加b
        name_pwd = b'用户名:密码'
        # 对用户名密码加密
        encode_name_pwd = base64.b64decode(name_pwd)        # 设置http头
        request.headers['Proxy-Authorization'] = 'Bisic ' + encode_name_pwd.decode()

将你的中间件添加到settings.py的DOWNLOADER_MIDDLEWARES配置中

DOWNLOADER_MIDDLEWARES = {   # 'scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware': 543,
   'scrapy_demo.middlewares.DoubanProcess': 543,
}

设置随机User-Agent

在middlewares.py文件中进行编写

创建一个中间件:

class DoubanUserAgent(object):def process_request(self,request,spider):
    # user-agent列表
    USER_AGENT_LIST = [        'MSIE (MSIE 6.0; X11; Linux; i686) Opera 7.23',        'Opera/9.20 (Macintosh; Intel Mac OS X; U; en)',        'Opera/9.0 (Macintosh; PPC Mac OS X; U; en)',        'iTunes/9.0.3 (Macintosh; U; Intel Mac OS X 10_6_2; en-ca)',        'Mozilla/4.76 [en_jp] (X11; U; SunOS 5.8 sun4u)',        'iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)',        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0',        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0',        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20120813 Firefox/16.0',        'Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)',        'Mozilla/4.8 [en] (X11; U; SunOS; 5.7 sun4u)'
    ]    # 使用random随机从列表中选择一个user-agent
    agent = random.choice(USER_AGENT_LIST)    # 修改请求头
    request.headers['User_Agent'] = agent

将user-agent中间件添加到 settings.py的DOWNLOADER_MIDDLEWARES配置中(优先级不能相同)

DOWNLOADER_MIDDLEWARES = {   # 'scrapy_demo.middlewares.ScrapyDemoDownloaderMiddleware': 543,
   'scrapy_demo.middlewares.DoubanProcess': 543,   'scrapy_demo.middlewares.DoubanUserAgent': 544,
}



作者:mocen_王琪
链接:https://www.jianshu.com/p/1d2e1a83cf05


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消