博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
scrapy爬虫流程
阅读量:6886 次
发布时间:2019-06-27

本文共 6396 字,大约阅读时间需要 21 分钟。

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
来指定“递归”的层数

你可能感兴趣的文章
centos虚拟机实现上网
查看>>
我的友情链接
查看>>
处理HP-UNIX面板灯报警及配置MP
查看>>
Java多线程和线程池
查看>>
配置docker使用overlay2存储
查看>>
邮件服务器迁移方案让企业邮箱安心“搬家”
查看>>
SCDPM常见报错解答
查看>>
OA项目笔记
查看>>
引用计数 vs. GC
查看>>
jquery实用的一些方法
查看>>
质数方阵
查看>>
jQuery $.each用法
查看>>
C语言结构体指针成员强制类型转换
查看>>
5.31 dockrer
查看>>
FreeCodeCamp----Intermediate Algorithm Scripting解法
查看>>
软件工程第二章 习题2 第4题
查看>>
《JavaScript设计模式与开发实践》读书笔记之命令模式
查看>>
hdu Problem 1242 Rescue bfs + 优先队列
查看>>
HDU-1507-Uncle Tom's Inherited Land*
查看>>
force里面的射线检测
查看>>