1 2 3 4 5 6 7 | 一、scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 其可以应用在数据挖掘,信息处 理或存储历史数据等一系列的程序中。其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也 可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。 Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。 Scrapy 使用了 Twisted异步网络库来处理网络通讯。整体架构大致如下: |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | Scrapy主要包括了以下组件: 1. 引擎(Scrapy) 用来处理整个系统的数据流处理, 触发事务(框架核心) 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. 引擎从调度器中取出一个链接(URL)用于接下来的抓取 2. 引擎把URL封装成一个请求(Request)传给下载器 3. 下载器把资源下载下来,并封装成应答包(Response) 4. 爬虫解析Response 5. 解析出实体(Item),则交给实体管道进行进一步的处理 6. 解析出的是链接(URL),则把URL交给调度器等待抓取 二、安装 1. linux #pip3 install scrapy 2.windows a. pip3 install wheel b. 下载twisted c. 进入下载目录,执行 pip3 install Twisted17. 1.0cp35cp35mwin_amd64 .whl d. pip3 install scrapy e. 下载并安装pywin32: 三、基本命令 1. scrapy startproject 项目名称 - 在当前目录中创建中创建一个项目文件(类似于Django) 2.scrapy genspider [ - t template] <name> <domain> - 创建爬虫应用 scrapy gensipider - t basic oldboy oldboy.com scrapy gensipider - t xmlfeed autohome autohome.com.cn 查看所有命令:scrapy gensipider - l 查看模板命令:scrapy gensipider - d 模板名称 3. scrapy list - 展示爬虫应用列表 4. scrapy crawl 爬虫应用名称 - 运行单独爬虫应用 5. 项目结构以及爬虫应用简介 project_name / scrapy.cfg project_name / __init__.py items.py pipelines.py settings.py spiders / __init__.py 爬虫 1.py 爬虫 2.py 爬虫 3.py 文件说明: scrapy.cfg 项目的主配置信息。(真正爬虫相关的配置信息在settings.py文件中) items.py 设置数据存储模板,用于结构化数据,如:Django的Model pipelines 数据处理行为,如:一般结构化的数据持久化 settings.py 配置文件,如:递归的层数、并发数,延迟下载等 spiders 爬虫目录,如:创建文件,编写爬虫规则 注意:一般创建爬虫文件时,以网站域名命名 爬虫文件oldboy.py例子: import scrapy class XiaoHuarSpider(scrapy.spiders.Spider): name = "xiaohuar" allowed_domains = [ "xiaohuar.com" ] start_urls = [ "http://www.xiaohuar.com/hua/" , ] def parse( self ,response): print (response.text) 注意windows编码: import sys,os sys.stdout = io.TextIOWrapper(sys.stdout. buffer ,encoding = 'gb18030' ) 四、项目示例 import scrapy from scrapy.selector import HtmlXPathSelector from scrapy.http.request import Request class DigSpider(scrapy.Spider): name = "dig" allowed_domains = [ "chouti.com" ] start_urls = [ 'http://dig.chouti.com' , ] has_request_set = {} def parse( self , response): print (response.url) hxs = HtmlXPathSelector(response) page_list = hxs.select( '//div[@id="dig_lcpage"]//a[re:test(@href, "/all/hot/recent/\d+")]/@href' ).extract() for page in page_list: page_url = 'http://dig.chouti.com{0}' . format (page) key = self .md5(page_url) if key in self .has_request_set: pass else : self .has_request_set[key] = page_url obj = Request(url = page_url, method = 'GET' ,callback = self .parse) yield obj @ staticmethod def md5(val): import hashlib ha = hashlib.md5() ha.update(bytes(val, encoding = 'utf-8' )) key = ha.hexdigest() return key 执行命令: scrapy crawl dig - - nolog Request是一个封装用户请求的类,在回调函数中 yield 该对象表示继续访问 HtmlXpathSelector用于结构化HTML代码并提供选择器功能 登录知乎: import scrapy from scrapy.selector import HtmlXPathSelector from scrapy.http.request import Request from scrapy.http.cookies import CookieJar from scrapy import FormRequest class ChouTiSpider(scrapy.Spider): # 爬虫应用的名称,通过此名称启动爬虫命令 name = "chouti" # 允许的域名 allowed_domains = [ "chouti.com" ] cookie_dict = {} has_request_set = {} def start_requests( self ): url = 'http://dig.chouti.com/' # return [Request(url=url, callback=self.login)] yield Request(url = url, callback = self .login) def login( self , response): cookie_jar = CookieJar() cookie_jar.extract_cookies(response, response.request) for k, v in cookie_jar._cookies.items(): for i, j in v.items(): for m, n in j.items(): self .cookie_dict[m] = n.value req = Request( url = 'http://dig.chouti.com/login' , method = 'POST' , headers = { 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' }, body = 'phone=xxxxxxxx&password=xxxxxx&oneMonth=1' , cookies = self .cookie_dict, callback = self .check_login ) yield req def check_login( self , response): req = Request( url = 'http://dig.chouti.com/' , method = 'GET' , callback = self .show, cookies = self .cookie_dict, dont_filter = True ) yield req def show( self , response): # print(response) hxs = HtmlXPathSelector(response) news_list = hxs.select( '//div[@id="content-list"]/div[@class="item"]' ) for new in news_list: # temp = new.xpath('div/div[@class="part2"]/@share-linkid').extract() link_id = new.xpath( '*/div[@class="part2"]/@share-linkid' ).extract_first() yield Request( url = 'http://dig.chouti.com/link/vote?linksId=%s' % (link_id,), method = 'POST' , cookies = self .cookie_dict, callback = self .do_favor ) page_list = hxs.select( '//div[@id="dig_lcpage"]//a[re:test(@href, "/all/hot/recent/\d+")]/@href' ).extract() for page in page_list: page_url = 'http://dig.chouti.com%s' % page import hashlib hash = hashlib.md5() hash .update(bytes(page_url,encoding = 'utf-8' )) key = hash .hexdigest() if key in self .has_request_set: pass else : self .has_request_set[key] = page_url yield Request( url = page_url, method = 'GET' , callback = self .show ) def do_favor( self , response): print (response.text) 注: settings.py中设置DEPTH_LIMIT = 1 来指定“递归”的层数 |
本文转自小白的希望 51CTO博客,原文链接:http://blog.51cto.com/haoyonghui/1976482 ,如需转载请自行联系原作者