Scrapy初体验

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

scrapy的架构图:

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']

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

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 pymongo
from 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

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

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,
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341