scrapy 抓取分页文章合并数据

很多网站为了获取 pv, 会把一篇完整的文章分成多页, 这也给爬虫抓取造成了一些小问题。


分页文章

常规的做法是先解析第一页数据,保存到 item , 再检测是否存在下一页, 如果存在,重复执行抓取函数, 直到到最后一页停止。
但是在scrapy 中有一个问题, scrapy 中的回调函数无法返回值,抓取的文章正文无法返回, 所以这里可以用 request 的 meta 属性单向传递item变量到抓取函数中。

def parse_article(self, response):
        """parse article content

        Arguments:
            response {[type]} -- [description]
        """
        selector = Selector(response)
        article = ArticleItem()
        # 先获取第一页的文章正文
        article['content'] = selector.xpath(
            '//article[@class="article-content"]').get()
        
        # 拆分最后一页的 url, 可以得到文章的base url 和总页数
        page_end_url = selector.xpath(
            '//div[@class="pagination"]/ul/li/a/@href').extract()[-1]
        page_base_url, page_count = re.findall(
            '(.*?)_(.*?).html', page_end_url)[0]
        page_count = int(page_count)

        for page in range(2, page_count + 1):
            # 构造出分页 url
            url = page_base_url + '_{}.html'.format(page)
            # 手动生成 Request 请求, 注意函数中的 priority 参数, 代表了 Request 是按顺序执行的, 值越大, 优先级越高
            request = Request(url=url, callback=self.parse_content, priority=-page)
            # 向 self.parse_content 函数传递 item 变量
            request.meta['article'] = article
            yield request

self.parse_content 中主要是抓取文章正文, 并存入 item 的操作

def parse_content(self, response):
        selector = Selector(response)
        article = response.meta['article']
        # 注意这里对 article['content']的操作是 +=, 这样不会清空上一页保存的数据
        article['content'] += selector.xpath('//article[@class="article-content"]').get()
        yield article

Reference: Requests and Responses

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容