Python 分布式爬虫框架 Scrapy 4-7 文章封面的保存

首先,封面图是在列表页。而parse函数是解析列表页的,所以封面图的解析要放在parse函数中。

parse函数与parse_detail函数是如何交互的呢?可以看到,就是下面这句:

yield Request(url=parse.urljoin(response.url, url), callback=self.parse_detail)

所以,我们需要在执行这句的时候,把封面信息带过去,从而能在parse_detail中的response中找到封面图信息。当然了,带过去之前,我们首先要将封面图的url解析出来。

因为封面url与文章的链接一样,与文章是一一对应的,故而我们在解析时,首先获取文章结点,遍历时,对于文章结点进行其链接与封面如url的提取。先使用shell进行调试:
 

>>> article_nodes_selector = response.xpath('//div[@id="news_list"]/div[@class="news_block"]/div[@class="content"]')
>>> article_urls = article_nodes_selector.xpath('h2/a/@href').extract()
>>> front_images_urls = article_nodes_selector.xpath('div[@class="entry_summary"]/a/img/@src').extract()
>>> len(article_urls)
30
>>> len(front_images_urls)
21

由上可见,有些文章是没有封面图的,这提示了我们接下来的编程细节。

对于下面的代码:

# 获取文章列表页中的文章的url,交给scrapy下载后,进行具体字段的解析
articles_link = response.xpath('//*[@class="news_entry"]/a/@href').extract()
for url in articles_link:
    yield Request(url=parse.urljoin(response.url, url), callback=self.parse_detail)
    pass

我们修改成:

# 获取文章列表页中的文章的url,交给scrapy下载后,进行具体字段的解析
article_nodes_selector = response.xpath('//div[@id="news_list"]/div[@class="news_block"]/div[@class="content"]')
for article_node_selector in article_nodes_selector:
	article_url = article_node_selector.xpath('h2/a/@href').extract_first()
	front_image_url = article_node_selector.xpath('div[@class="entry_summary"]/a/img/@src').extract_first("")
	yield Request(url=parse.urljoin(response.url, article_url),
				  meta = {"front_image_url": front_image_url},
				  callback=self.parse_detail)
	pass

在yield一个Request的时候,我们添加了一个meta,实现了封面信息的传递。

调试发现,response的meta中,确实有了front_image_url这一字段:

这样,在parse_detail中,加一句:

扫描二维码关注公众号,回复: 8765938 查看本文章
# 封面图
front_image_url = response.meta.get('front_image_url', '')

即可成功获得封面图。

cnblogs.py中的代码:

# -*- coding: utf-8 -*-
import scrapy
import re
from scrapy.http import Request
from urllib import parse


class CnblogsSpider(scrapy.Spider):
    name = 'cnblogs'
    allowed_domains = ['news.cnblogs.com']  # 允许的域名
    start_urls = ['https://news.cnblogs.com']  # 起始url

    def parse(self, response):
        """
        1. 获取文章列表页中的文章的url,交给scrapy下载后,进行具体字段的解析
        2. 获取下一页的url,交给scrapy进行下载,下载完成后交给parse
        """
        # 获取文章列表页中的文章的url,交给scrapy下载后,进行具体字段的解析
        article_nodes_selector = response.xpath('//div[@id="news_list"]/div[@class="news_block"]/div[@class="content"]')
        for article_node_selector in article_nodes_selector:
            article_url = article_node_selector.xpath('h2/a/@href').extract_first()
            front_image_url = article_node_selector.xpath('div[@class="entry_summary"]/a/img/@src').extract_first("")
            yield Request(url=parse.urljoin(response.url, article_url),
                          meta = {"front_image_url": front_image_url},
                          callback=self.parse_detail)
            pass

        pass

        # 获取下一页的url,交给scrapy进行下载,下载完成后交给parse
        next_url = response.xpath('//div[@class="pager"]/a[not(@class)]/@href').extract_first('end')
        if next_url != 'end':
            next_url = parse.urljoin(response.url, next_url)
            yield Request(url=next_url, callback=self.parse)
            pass

        pass

    def parse_detail(self, response):
        """
        解析文章具体字段
        """
        if 'account' in response.url:
            pass
        else:
            # 标题
            title = response.xpath('//*[@id="news_title"]/a/text()').extract_first("Untitled")
            # 发布日期
            create_date = re.findall('\d{4}-\d{2}-\d{2}', response.xpath('//*[@id="news_info"]/span[2]/text()').extract_first("0000-00-00"))[0]
            # 封面图
            front_image_url = response.meta.get('front_image_url', '')
            # 正文
            content = response.xpath('//*[@id="news_body"]').extract_first("No content")
            # 标签
            tags = ','.join(response.xpath('//*[@id="news_more_info"]/div/a/text()').extract())
            # 来源
            source = response.xpath('//*[@id="link_source2"]/text()').extract_first('Unknown')
            pass

        pass

 

发布了101 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/liujh_990807/article/details/100048426
今日推荐