scrapy分页抓取网页(豆瓣社科小组,我们将首页地址作为_url参数,从页面源码找到)

优采云 发布时间: 2022-02-26 20:08

  scrapy分页抓取网页(豆瓣社科小组,我们将首页地址作为_url参数,从页面源码找到)

  2015 年 6 月 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次呢?更严重的是,会不会陷入死循环?比如从第一页提取第二页-》处理第二页,提取第一页-》处理第一页,提取第二页-》...

  我们直接运行程序,现在看看我们的打印语句:“->”前面表示当前页地址,后面是从当前页中提取的分页地址。为了简化输出,只提取用于标识分页的“开始”。范围。

  结果如下:

  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 的 Rule 感觉更方便。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线