学了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安装:
开始
创建项目:
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 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
运行之后就可以在数据库中看到咱们已经添加了数据
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