scrapy分页抓取网页(豆瓣社科小组,我们将首页地址作为_url参数,从页面源码找到)
优采云 发布时间: 2021-12-31 20:10scrapy分页抓取网页(豆瓣社科小组,我们将首页地址作为_url参数,从页面源码找到)
2015-06-23 更新:
写这篇文章的时候,我还没有遇到具体的场景。只是觉得有这样的方法,就写下来了。
我今天刚刚满足了这个需求。抓取BBS内容,版块首页只显示标题、作者和发表时间。需要做的就是按时间过滤,每天抓取最新的内容。使用Rule规则提取URL后,只保留链接地址,丢失上下文信息(发布时间)。如果要过滤,只能得到链接内容爬取后的时间,实际上造成了不必要的浪费。使用本文文章的方法在抓取链接前进行过滤,避免抓取无用数据。
第一个scrapy爬虫开始了(3)- 使用规则实现多页爬取给出了使用CrawlSpider Rule实现多页爬取的方法,其实直接使用BaseSpider也可以实现多页爬取.
具体思路:以我们豆瓣团队为例。我们将首页地址作为start_url参数,从页面源码中查找剩余的页面,如下:
<前页
1
2
3
4
5
6
7
8
9
后页>
可以提取每个页面的地址,多页面爬取的思路是把地址封装成一个Request作为回调函数parse的返回值(不影响item的返回值),并为这些页面地址函数指定相应的回调。由于首页和分页在形式上完全一致(首页本身也是一个页面),可以直接指定parse作为回调函数。
代码如下:
from scrapy.spider import BaseSpider
from douban.items import DoubanItem
from scrapy.http import Request
class GroupSpider(BaseSpider):
name = "douban"
allowed_domains = ["douban.com"]
start_urls = ["http://www.douban.com/group/explore?start=0&tag=%E7%A4%BE%E7%A7%91"]
#默认的回调函数
def parse(self, response):
print "+"*20, response.url
item = DoubanItem()
sel = response.xpath("//div[@class='group-list']/div[@class='result']")
for s in sel:
info = s.xpath("div/div/h3/a/text()").extract()[0]
item["groupName"] = info
yield item
#处理当前页面里的分页 -- 封装为Request返回
sel = response.xpath("//div[@class='paginator']/a/@href").extract()
for s in sel:
print response.url.split("?")[1].split("&")[0], "->", s.split("?")[1].split("&")[0]
yield Request(s, callback=self.parse)
之前使用了所有的CrawlSpider,但是这里替换了BaseSpider,不支持Rule;同时在原有回调函数的基础上增加了分页处理。首先是提取地址,然后打印语句,后面会讲,最后返回Request。
在写这段代码的时候,感觉有一个问题:由于每个页面指定的回调函数都是parse,所以就相当于为每个页面提取了一个页面地址,这样实际上每个页面地址都在返回结束N次,scrapy会在实际处理中对每个地址处理N次吗?更严重的是,会不会陷入死循环?比如从第一页提取第二页-》处理第二页,提取第一页-》处理第一页,提取第二页-》......
让我们运行程序看看。现在来看看我们的print语句:“->”代表当前页面地址,后面是从当前页面中提取出来的页面地址。为了精简输出,只提取用于识别页面的那个。 “开始”参数。
运行结果如下:
class GroupSpider(BaseSpider):
++++++++++++++++++++ http://www.douban.com/group/explore?start=0&tag=%E7%A4%BE%E7%A7%91
start=0 -> start=20
start=0 -> start=40
start=0 -> start=60
start=0 -> start=80
start=0 -> start=100
start=0 -> start=120
start=0 -> start=140
start=0 -> start=160
++++++++++++++++++++ http://www.douban.com/group/explore?start=40&tag=%E7%A4%BE%E7%A7%91
start=40 -> start=0
start=40 -> start=20
start=40 -> start=60
start=40 -> start=80
start=40 -> start=100
start=40 -> start=120
start=40 -> start=140
start=40 -> start=160
++++++++++++++++++++ http://www.douban.com/group/explore?start=20&tag=%E7%A4%BE%E7%A7%91
start=20 -> start=0
start=20 -> start=40
++++++++++++++++++++ http://www.douban.com/group/explore?start=60&tag=%E7%A4%BE%E7%A7%91
start=20 -> start=60
start=20 -> start=80
start=20 -> start=100
start=60 -> start=0
start=60 -> start=20
++++++++++++++++++++ http://www.douban.com/group/explore?start=100&tag=%E7%A4%BE%E7%A7%91
++++++++++++++++++++ http://www.douban.com/group/explore?start=80&tag=%E7%A4%BE%E7%A7%91
++++++++++++++++++++ http://www.douban.com/group/explore?start=140&tag=%E7%A4%BE%E7%A7%91
start=20 -> start=120
start=20 -> start=140
start=20 -> start=160
start=60 -> start=40
start=60 -> start=80
start=60 -> start=100
start=100 -> start=0
start=100 -> start=20
start=80 -> start=0
start=80 -> start=20
start=140 -> start=0
start=140 -> start=20
++++++++++++++++++++ http://www.douban.com/group/explore?start=160&tag=%E7%A4%BE%E7%A7%91
start=160 -> start=0
++++++++++++++++++++ http://www.douban.com/group/explore?start=120&tag=%E7%A4%BE%E7%A7%91
start=120 -> start=0
start=60 -> start=120
start=60 -> start=140
start=60 -> start=160
start=100 -> start=40
start=100 -> start=60
start=100 -> start=80
start=80 -> start=40
start=80 -> start=60
start=80 -> start=100
start=140 -> start=40
start=140 -> start=60
start=140 -> start=80
start=160 -> start=20
start=160 -> start=40
start=160 -> start=60
start=120 -> start=20
start=120 -> start=40
start=120 -> start=60
++++++++++++++++++++ http://www.douban.com/group/explore?start=0&tag=%E7%A4%BE%E7%A7%91
start=100 -> start=120
start=100 -> start=140
start=100 -> start=160
start=80 -> start=120
start=80 -> start=140
start=80 -> start=160
start=140 -> start=100
start=140 -> start=120
start=140 -> start=160
start=160 -> start=80
start=160 -> start=100
start=160 -> start=120
start=120 -> start=80
start=120 -> start=100
start=120 -> start=140
start=0 -> start=20
start=0 -> start=40
start=0 -> start=60
start=160 -> start=140
start=120 -> start=160
start=0 -> start=80
start=0 -> start=100
start=0 -> start=120
start=0 -> start=140
start=0 -> start=160
输出有点太多了,如你所见:
1.每个页面地址确实返回了多次;
2. 没有陷入死循环,没有重复处理;
3. 处理过程乱序;
这表明scrapy本身已经进行了重复数据删除并使用线程进行数据提取操作。
好的,任务完成。使用CrawlSpider的规则感觉更方便。