爬取新闻新浪页面
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
<code>items.py</code>
<code>import</code> <code>scrapy</code>
<code>class</code> <code>SinaItem(scrapy.Item):</code>
<code> </code><code># define the fields for your item here like:</code>
<code> </code><code># name = scrapy.Field()</code>
<code> </code><code>pass</code>
<code>class</code> <code>SinanewsItem(scrapy.Item):</code>
<code> </code><code>#大类的标题和url</code>
<code> </code><code>parentTitle </code><code>=</code> <code>scrapy.Field()</code>
<code> </code><code>parentUrls </code><code>=</code> <code>scrapy.Field()</code>
<code> </code><code>#小类的标题和子url</code>
<code> </code><code>subTitle </code><code>=</code> <code>scrapy.Field()</code>
<code> </code><code>subUrls </code><code>=</code> <code>scrapy.Field()</code>
<code> </code><code>#小类目录存储路径</code>
<code> </code><code>subFilename </code><code>=</code> <code>scrapy.Field()</code>
<code> </code><code>#小类下的子链接</code>
<code> </code><code>sonUrl </code><code>=</code> <code>scrapy.Field()</code>
<code> </code><code>#文章标题和内容</code>
<code> </code><code>head </code><code>=</code> <code>scrapy.Field()</code>
<code> </code><code>content </code><code>=</code> <code>scrapy.Field()</code>
<code> </code>
<code>爬虫脚本sina01.py</code>
<code># -*- coding: utf-8 -*-</code>
<code>from</code> <code>..items </code><code>import</code> <code>SinanewsItem</code>
<code>from</code> <code>scrapy_redis.spiders </code><code>import</code> <code>RedisSpider</code>
<code>class</code> <code>Sina01Spider(RedisSpider):</code>
<code> </code><code>name </code><code>=</code> <code>'sina01'</code>
<code> </code><code>#启动爬虫时的命令</code>
<code> </code><code>redis_key </code><code>=</code> <code>"sinaspider:start_urls"</code>
<code> </code><code>#allowed_domains = ['sina.com']</code>
<code> </code><code># start_urls = ['http://sina.com/']</code>
<code> </code><code>#动态定义爬虫取域范围</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>, </code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs):</code>
<code> </code><code>domain </code><code>=</code> <code>kwargs.pop(</code><code>'domain'</code><code>, '')</code>
<code> </code><code>self</code><code>.allowed_domains </code><code>=</code> <code>filter</code><code>(</code><code>None</code><code>, domain.split(</code><code>','</code><code>))</code>
<code> </code><code>super</code><code>(Sina01Spider, </code><code>self</code><code>).__init__(</code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs)</code>
<code> </code><code>def</code> <code>parse(</code><code>self</code><code>, response):</code>
<code> </code><code>items </code><code>=</code> <code>[]</code>
<code> </code><code>#所有大类的url和标题</code>
<code> </code><code>parentUrls </code><code>=</code> <code>response.xpath(</code><code>'//div[@id="tab01"]/div/h3/a/@href'</code><code>).extract()</code>
<code> </code><code>parentTitle </code><code>=</code> <code>response.xpath(</code><code>'//div[@id="tab01"]/div/h3/a/text()'</code><code>).extract()</code>
<code> </code><code>#所有小类的url和标题</code>
<code> </code><code>subUrls </code><code>=</code> <code>response.xpath(</code><code>'//div[@id="tab01"]/div/ul/li/a/@href'</code><code>).extract()</code>
<code> </code><code>subTitle </code><code>=</code> <code>response.xpath(</code><code>'//div[@id="tab01"]/div/ul/li/a/text()'</code><code>).extract()</code>
<code> </code><code>#爬取所有大类</code>
<code> </code><code>for</code> <code>i </code><code>in</code> <code>range</code><code>(</code><code>0</code><code>, </code><code>len</code><code>(parentTitle)):</code>
<code> </code><code>#爬取所有小类</code>
<code> </code><code>for</code> <code>j </code><code>in</code> <code>range</code><code>(</code><code>0</code><code>, </code><code>len</code><code>(subUrls)):</code>
<code> </code><code>item </code><code>=</code> <code>SinanewsItem()</code>
<code> </code><code>#保存大类的title和urls</code>
<code> </code><code>item[</code><code>'parentTitle'</code><code>] </code><code>=</code> <code>parentTitle[i]</code>
<code> </code><code>item[</code><code>'parentUrls'</code><code>] </code><code>=</code> <code>parentUrls[i]</code>
<code> </code><code>#检查小类的url是否以同类别大类url开头,如果是返回True</code>
<code> </code><code>if_belong </code><code>=</code> <code>subUrls[j].startswith(item[</code><code>'parentUrls'</code><code>])</code>
<code> </code><code>if</code> <code>(if_belong):</code>
<code> </code><code># 存储小类url、title和filename字段数据</code>
<code> </code><code>item[</code><code>'subUrls'</code><code>] </code><code>=</code> <code>subUrls[j]</code>
<code> </code><code>item[</code><code>'subTitle'</code><code>] </code><code>=</code> <code>subTitle[j]</code>
<code> </code><code>items.append(item)</code>
<code> </code><code># 发送每个小类url的Request请求,得到Response连同包含meta数据 一同交给回调函数 second_parse 方法处理</code>
<code> </code><code>for</code> <code>item </code><code>in</code> <code>items:</code>
<code> </code><code>yield</code> <code>scrapy.Request(url</code><code>=</code><code>item[</code><code>'subUrls'</code><code>], meta</code><code>=</code><code>{</code><code>'meta_1'</code><code>:item}, callback</code><code>=</code><code>self</code><code>.second_parse)</code>
<code> </code><code>#对于返回的小类的url,在进行递归请求</code>
<code> </code><code>def</code> <code>second_parse(</code><code>self</code><code>, response):</code>
<code> </code><code>#提取每次Response的meta数据</code>
<code> </code><code>meta_1 </code><code>=</code> <code>response.meta[</code><code>'meta_1'</code><code>]</code>
<code> </code><code>#取出小类的所有子链接</code>
<code> </code><code>sonUrls </code><code>=</code> <code>response.xpath(</code><code>'//a/@href'</code><code>).extract()</code>
<code> </code><code>for</code> <code>i </code><code>in</code> <code>range</code><code>(</code><code>0</code><code>, </code><code>len</code><code>(sonUrls)):</code>
<code> </code><code>#检查每个链接是否以大类url开头、以.shtml结尾,如果是返回True</code>
<code> </code><code>if_belong </code><code>=</code> <code>sonUrls[i].endswith(</code><code>'.shtml'</code><code>) </code><code>and</code> <code>sonUrls[i].startwith(meta_1[parentUrls])</code>
<code> </code><code># 如果属于本大类,获取字段值放在同一个item下便于传输</code>
<code> </code><code>if</code><code>(if_belong):</code>
<code> </code><code>item[</code><code>'parentTitle'</code><code>] </code><code>=</code> <code>meta_1[</code><code>'parentTitle'</code><code>]</code>
<code> </code><code>item[</code><code>'parentUrls'</code><code>] </code><code>=</code> <code>meta_1[</code><code>'parentUrls'</code><code>]</code>
<code> </code><code>item[</code><code>'subUrls'</code><code>] </code><code>=</code> <code>meta_1[</code><code>'subUrls'</code><code>]</code>
<code> </code><code>item[</code><code>'subTitle'</code><code>] </code><code>=</code> <code>meta_1[</code><code>'subTitle'</code><code>]</code>
<code> </code><code>item[</code><code>'sonUrls'</code><code>] </code><code>=</code> <code>sonUrls[i]</code>
<code> </code><code>items.append(item)</code>
<code> </code><code># 发送每个小类下子链接url的Request请求,得到Response后连同包含meta数据 一同交给回调函数 detail_parse 方法处理</code>
<code> </code><code>yield</code> <code>scrapy.Request(url</code><code>=</code><code>item[</code><code>'sonUrls'</code><code>],meta</code><code>=</code><code>{</code><code>'meta_2'</code><code>:item},callback</code><code>=</code><code>self</code><code>.detail_parse)</code>
<code> </code><code>#数据解析方法,获取文章标题和内容</code>
<code> </code><code>def</code> <code>detail_parse(</code><code>self</code><code>, response):</code>
<code> </code><code>item </code><code>=</code> <code>response.meta[</code><code>'meta_2'</code><code>]</code>
<code> </code><code>content </code><code>=</code> <code>""</code>
<code> </code><code>head </code><code>=</code> <code>response.xpath(</code><code>'/h1[@id="main_title"]/text()'</code><code>)</code>
<code> </code><code>content_list </code><code>=</code> <code>response.xpath(</code><code>'//div[@id="artibody"]/p/text()'</code><code>).extract()</code>
<code> </code><code>#将p标签里的文本内容 合并到一起</code>
<code> </code><code>for</code> <code>content_one </code><code>in</code> <code>content_list:</code>
<code> </code><code>content </code><code>+</code><code>=</code> <code>content_one</code>
<code> </code><code>item[</code><code>'head'</code><code>] </code><code>=</code> <code>head[</code><code>0</code><code>] </code><code>if</code> <code>len</code><code>(head) > </code><code>0</code> <code>else</code> <code>"NULL"</code>
<code> </code><code>item[</code><code>'content'</code><code>] </code><code>=</code> <code>content</code>
<code> </code><code>yield</code> <code>item</code>
<code> </code>
<code> </code><code>settings.py添加</code>
<code> </code><code># 使用scrapy-redis里的去重组件,不使用scrapy默认的去重方式</code>
<code>DUPEFILTER_CLASS </code><code>=</code> <code>"scrapy_redis.dupefilter.RFPDupeFilter"</code>
<code># 使用scrapy-redis里的调度器组件,不使用默认的调度器</code>
<code>SCHEDULER </code><code>=</code> <code>"scrapy_redis.scheduler.Scheduler"</code>
<code># 允许暂停,redis请求记录不丢失</code>
<code>SCHEDULER_PERSIST </code><code>=</code> <code>True</code>
<code># 默认的scrapy-redis请求队列形式(按优先级)</code>
<code>SCHEDULER_QUEUE_CLASS </code><code>=</code> <code>"scrapy_redis.queue.SpiderPriorityQueue"</code>
<code># 队列形式,请求先进先出</code>
<code>#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"</code>
<code># 栈形式,请求先进后出</code>
<code>#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"</code>
<code># 只是将数据放到redis数据库,不需要写pipelines文件</code>
<code>ITEM_PIPELINES </code><code>=</code> <code>{</code>
<code># 'Sina.pipelines.SinaPipeline': 300,</code>
<code> </code><code>'scrapy_redis.pipelines.RedisPipeline'</code><code>: </code><code>400</code><code>,</code>
<code>}</code>
<code># LOG_LEVEL = 'DEBUG'</code>
<code># Introduce an artifical delay to make use of parallelism. to speed up the</code>
<code># crawl.</code>
<code>DOWNLOAD_DELAY </code><code>=</code> <code>1</code>
<code># 指定数据库的主机IP</code>
<code>REDIS_HOST </code><code>=</code> <code>"localhost"</code>
<code># 指定数据库的端口号</code>
<code>REDIS_PORT </code><code>=</code> <code>6379</code>
<code>打开redis客户端添加url测试</code>
<code>lpush sinaspider:start_urls http:</code><code>/</code><code>/</code><code>news.sina.com.cn</code><code>/</code><code>guide</code><code>/</code>
本文转自小白的希望 51CTO博客,原文链接:http://blog.51cto.com/haoyonghui/1978095,如需转载请自行联系原作者