首页 > 代码库 > python scrapy学习笔记
python scrapy学习笔记
scrapy是python最有名的爬虫框架之一,可以很方便的进行web抓取,并且提供了很强的定制型。
一、安装scrapy
# pip install scrapy
二、基本使用
1、初始化scrapy项目
# scrapy startproject myscrapy
初始化完成后的目录结构
# tree . ├── myscrapy │ ├── __init__.py │ ├── items.py # 设置数据存储模板,用于结构化数据 │ ├── middlewares.py # 中间件,相当于钩子,对爬去前后做预处理 │ ├── pipelines.py # 管道模块,处理spider模块分析好的数据,如保存入库等 │ ├── settings.py # 配置文件,如并发数,是否开启缓存 │ └── spiders │ ├── __init__.py │ └── myspider.py └── scrapy.cfg # 项目的配置文件
一个例子爬取当当网的首页
#!/usr/bin/python #coding:utf-8 import scrapy class DangDang(scrapy.Spider): # 必须定义 name = "dangdang" # 初始urls start_urls = [ "http://www.dangdang.com" ] # 默认response处理函数 def parse(self, response): # 抓取start_urls页面,自动执行parse回调函数 current_url = response.url # 当前请求的URL body = response.body # 请求的内容 print ‘请求的URL: {}\n请求的内容: {}‘.format(current_url,body)
运行
# scrapy crawl dangdang # 方式1 # scrapy runspider dangdang.py # 方式2
爬虫开始爬取start_urls定义的url,并输出到文件中,最后输出爬去报告,会输出爬取得统计结果
2、通过代码运行爬虫
每次进入控制台运行爬虫还是比较麻烦的,而且不好调试,我们可以通过CrawlerProcess通过代码运行爬虫,新建一个模块run.py#!/usr/bin/python #coding:utf-8 from scrapy.crawler import CrawlerProcess from scrapy.utils.project import get_project_settings from spiders.dangdang import DangDang # 获取setting.py模块的设置 settings = get_project_settings() process = CrawlerProcess(settings=settings) # 添加spider,可以多个 process.crawl(DangDang) # 启动爬虫,阻塞知道爬取结束 process.start()
只需要执行python run.py就可以执行爬虫
三、Scrapy类
如上面的DmozSpider类,爬虫类继承自scrapy.Spider
1、常用属性
name
:爬虫的名字,必须唯一(如果在控制台使用的话,必须配置)start_urls
:爬虫初始爬取的链接列表parse
:response结果处理函数custom_settings
:自定义配置,覆盖settings.py
中的默认配置
2、常用方法
start_requests
:启动爬虫的时候调用,默认是调用make_requests_from_url
方法爬取start_urls
的链接,可以在这个方法里面定制,如果重写了该方法,start_urls默认将不会被使用,可以在这个方法里面定制一些自定义的url,如登录,从数据库读取url等,本方法返回Request对象make_requests_from_url
:默认由start_requests
调用,可以配置Request对象,返回Request对象parse
:response到达spider的时候默认调用,如果在Request对象配置了callback函数,则不会调用,parse方法可以迭代返回Item
或Request
对象,如果返回Request对象,则会进行增量爬取
3、Request与Response对象
每个请求都是一个Request对象,Request对象定义了请求的相关信息(url, method, headers, body, cookie, priority)和回调的相关信息(meta, callback, dont_filter, errback),通常由spider迭代返回
其中meta相当于附加变量,可以在请求完成后通过response.meta访问请求完成后,会通过Response对象发送给spider处理,常用属性有(url, status, headers, body, request, meta)
四、选择器
基本的选择器
正则选择
1、基本的选择器
// ## 子孙
/ # 孩子
//div[@class=‘info‘][@id=‘1‘] # 属性选择器
//div/img/@src # div下所有img的src值
//div/a[1] # div下第一个<a>
//div/a[1]/text() # div下第一个<a>的值
例如
想要获取书名,可以写为: //ul[@class=‘list_aa listimg‘]/li//a/@title
查找方式
# 方法1,即将被废弃的 from scrapy.selector import HtmlXPathSelector hxs = HtmlXPathSelector(response) items_HtmlXPathSelector = hxs.select(‘//div[@class="item_list infinite_scroll"]/div‘) print(len(items_HtmlXPathSelector)) # 方法2 from scrapy.selector import Selector items_Selector = Selector(response=response).xpath(‘//div[@class="item_list infinite_scroll"]/div‘) print(len(items_Selector))
2、正则选择器
<body> <li class="item-"><a href="http://www.mamicode.com/link.html">first item</a></li> <li class="item-0"><a href="http://www.mamicode.com/link1.html">first item</a></li> <li class="item-1"><a href="http://www.mamicode.com/link2.html">second item</a></li> </body>
书写方法://li[re:test(@class, "item-\d*")]//@href
查找方式
ret = Selector(response=response).xpath(‘//li[re:test(@class, "item-\d*")]//@href‘).extract() # re ---- 通过正则进行匹配 # test -- 匹配
五、使用scrapy爬取网站聊天记录和用户头像
#!/usr/bin/python #coding:utf-8 import scrapy from scrapy.selector import Selector import os import requests class NextSpider(scrapy.spiders.Spider): name = ‘nextspider‘ start_urls = ["http://group.jobbole.com/27740/#comm-77724"] def parse(self,response): items_selector = Selector(response=response) items = items_selector.xpath(‘//ul[@class="cmnt-list"]/li‘) # print items for i in range(len(items)): srcs = items_selector.xpath(‘//ul[@class="cmnt-list"]/li[%d]//div[@class="cmnt-header"]/a/img/@src‘%i).extract() names = items_selector.xpath(‘//ul[@class="cmnt-list"]/li[%d]//div[@class="cmnt-header"]/div/span[1]/a/text()‘%i).extract() msgs = items_selector.xpath(‘//ul[@class="cmnt-list"]/li[%d]//div[@class="cmnt-body"]/p/text()‘%i).extract() if srcs and names and msgs: try: img_url = srcs[0] filename = names[0].encode(‘utf-8‘) msg = ‘,‘.join([i.encode(‘utf-8‘) for i in msgs[1:]]) print ‘用户ID: {}\n发表信息: {}‘.format(filename,msg) img_dir = ‘imgs‘ path = os.path.join(os.getcwd(),img_dir,filename+‘.png‘) r = requests.get(img_url) with open(path,‘wb‘) as f: for chunk in r.iter_content(chunk_size=1024): if chunk: f.write(chunk) f.flush() f.close() except Exception,e: print ‘错误: {}‘.format(e)
结果
用户ID: 小编辑 发表信息: 恭喜!,说说你是怎么追到的。然后再打广告 :) 用户ID: 迷路的兔纸--> 发表信息: 你这是赤果果的炫耀 用户ID: sorry丶 发表信息: 10月份去九寨沟,在青旅里面遇到我的那个她。 ... ...
图片
# ls imgs/ lishenluo.png sorry丶.png 寻找隐世快乐.png 小编辑.png 忠文.png 熊绎.png 连时光都吐了.png 迷路的兔纸-->.png
六、items.py中的Item类
初始化后默认的Item类
import scrapy class MyscrapyItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() pass
scrapy.Item的用法与python中的字典用法基本一样,只是做了一些安全限制,属性定义使用Field,这里只是进行了声明,而不是真正的属性,使用的时候通过键值对操作,不支持属性访问
七、Pipeline
spider负责爬虫的配置,item负责声明结构化数据,而对于数据的处理,在scrapy中使用管道的方式进行处理,只要注册过的管道都可以处理item数据(处理,过滤,保存)
示例:这里定义一个预处理管道PretreatmentPipeline.py,如果item的title为None,则设置为空字符串
class PretreatmentPipeline(object): def process_item(self, item, spider): if item[‘msgs‘]: # 不让msgs为空 item[‘msgs‘] = ‘‘ return item
八、setting.py文件
setting.py文件中为我们提供了许多自带的功能,例如缓存、多线程等等,只需要修改配置即可
1、缓存
# 打开缓存 HTTPCACHE_ENABLED = True # 设置缓存过期时间(单位:秒) #HTTPCACHE_EXPIRATION_SECS = 0 # 缓存路径(默认为:.scrapy/httpcache) HTTPCACHE_DIR = ‘httpcache‘ # 忽略的状态码 HTTPCACHE_IGNORE_HTTP_CODES = [] # 缓存模式(文件缓存) HTTPCACHE_STORAGE = ‘scrapy.extensions.httpcache.FilesystemCacheStorage‘
2、多线程
# 默认Request并发数:32 CONCURRENT_REQUESTS = 32 # 默认每个域名的并发数:16 CONCURRENT_REQUESTS_PER_DOMAIN = 16 # 每个IP的最大并发数:0表示忽略 CONCURRENT_REQUESTS_PER_IP = 16
python scrapy学习笔记