python爬虫日记本互联网科技程序员

Scrapy框架之带有分页的详情页面抓取

2017-09-26  本文已影响187人  HideOnStream

最近在动手搭建一个爬虫框架,在考虑到设计上的一些细节的时候遇到一些问题,比如,对于详情页面带有多页的如何恰当的实现?于是乎想参考Scrapy爬虫框架对于这个场景的实现,网上谷歌,有人给出思路,但是没有完整的实现,所以在这里呈现一个完整的例子。

假设我想采集某新闻网站数据,比如说news.7654.com,为了增加网站的pv,uv量,很多文章都这样,如http://news.7654.com/a/2184936178569937140_1?TAG=3_27,带有多个分页。如下图:

多页.png

采集一篇文章肯定不能只抓取它的第一页数据,那样是不完整的,那么该如何抓取全部的页面呢?大致思路是,在抓取到第一页的时候提取出需要的数据信息,然后查看是否还有下一页,如果有下一页,则提取出下一个页面的链接,生成一个Request对象,并且将刚才提取出来的有效信息作为meta参数传给这个Request对象,然后将这个Request对象交给Scrapy引擎,如果没有下一页,就将这些meta里面的信息整合起来,生成Item即可。

好了,看代码:

import re
import scrapy

from lxml import html
from lxml.html import clean
from urllib.parse import urljoin
from newsproject.items import NewsprojectItem


class NewsSpider(scrapy.Spider):
    name = 'news_spider'
    allowed_domains = ['news.7654.com']
    start_urls = ['http://news.7654.com/a/2184936178569937140_1?TAG=3_27']

    def parse(self, response):

        # 调用clean类,用于去掉非html标准标签,以及scripts脚本等。
        cleaner = clean.Cleaner()
        tree = html.fromstring(cleaner.clean_html(response.body.decode()))

        # 获得下一页的链接
        next_url = tree.xpath("//div[@class='detailaddnum pb15']/a[last()]/@href")

        # 获得当前页面新闻的全部文本
        article_tag = tree.xpath("//div[@class='detail_pagination']")[0]
        article_content = article_tag.xpath('string(//*)').strip(" ").replace("\n", "").replace("\r", "")

        # 如果有下一页链接
        if next_url and re.match(r'http://news.7654.com/a/[0-9]+_[0-9]+\?TAG=3_27', next_url[0]):
            if not response.meta.get('article_content'):
                response.meta.update({'article_content': [article_content]})
            else:
                response.meta['article_content'].append(article_content)
            yield scrapy.Request(urljoin(response.request.url, next_url[0]),
                                 meta=response.meta, callback=self.parse)
        else:
            article_detail = ""
            for content in response.meta['article_content']:
                article_detail += content
            item = NewsprojectItem()
            # 当前页面的有效信息也要整合到一起
            item['article_detail'] = article_detail + article_content
            yield item

注意:在找最后一页的时候一定要做正则校验,因为新闻类网站很喜欢在最后一页放一个广告类页面,这个网站还好,只是在最后一页给你推荐的是另一篇新闻;提取出的下一页链接可能是一个相对地址。

好了,如何利用Scrapy抓取详情页带分页的介绍就到这里,在最后抛出一个新的问题,新闻里面都喜欢带图片,那么如何在抓取文章的时候同时把图片也抓取?(关键不是抓取,是如何把图片和文章整合)

上一篇 下一篇

猜你喜欢

热点阅读