边学边敲边记之爬虫系列(八):Scrapy系统爬取伯乐在线

这里写图片描述

一、前言

上一篇边学边敲边记爬虫系列七给大家仔细讲解了如何用Xpath分类爬取医疗信息网站医疗器材名称和介绍图片,以及三种最常用的存储方法。
本篇是本系列的第八篇了,今天给大家讲讲如何用Scrapy分类系统爬取伯乐在线文章信息。

二、你不得不知道的 Knowledge

1.CSS选择器获取标签内容值和标签属性值
eg. <a href = "https://blog.csdn.net/qq_39241986">极简XksA的博客</a>
# 1.获取内容值
response.css("a::text").extract()
# 2.获取href属性值
response.css("a::attr(href)")
2.urllib包下的parse函数作用
# python3下
from urllib import parse
url_main = "https://blog.csdn.net"
post_url = "/qq_39241986"
'''
urljoin函数参数介绍:
    url_main :第一个参数为主域名;
    post_url :第二个参数为需补全部分;
'''
url= parse.urljoin(url_main,post_url)
print(url)
# result :
#    https://blog.csdn.net/qq_39241986

通过代码容易看出,urllib包下的parse函数作用是能够补全我们获取的不完全链接
(在上一篇中我们获取到的商品类别url就是不完全的url,当时是我们自己写方法修正的数据)

3.yield关键字介绍

一个带有 yield 的函数就是一个 generator(生成器),它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。

三、看代码,边学边敲边记Scrapy爬取伯乐在线

1.爬取逻辑思路分析

爬取逻辑思路
图上已经绘画和写的比较清楚了,一个简单思路就是:请求页面 -> 获取文章和下页链接 -> 获取文章详细信息 -> 翻页,再从头开始,一直到爬完所有页面,所有文章,下面我们具体动手试试。

2.调试方便,我们还是在cmd下用scrapy shell 进行调试
(1)获取主页面所有文章的url

1)页面分析:
页面分析文章url获取方法
通过图片上面标记,容易看出,我们要获取的文章url在 id 为archive的div下的class为post floated-thumb的div下的class为post-thumb的div下的a标签的href属性中,哈哈,读起来有点拗口,这里提供两种方法获取相应内容:
Xpath路径:

'//*[@id="archive"]/div/div[1]/a/@href'

CSS选择器:

# 注:因为post floated-thumb这个类名中 post和floated-thumb中间有个空格,表示两个类名,
# 我们可以直接根据后面部分来查找到这个class。(attr用来取属性值)
"#archive .floated-thumb .post-thumb a::attr(href)"

2)shell下运行结果

# 我选择的是Xpath获取,个人比较习惯
>>> response.xpath('//*[@id="archive"]/div/div[1]/a/@href').extract()
['http://blog.jobbole.com/114334/', 'http://blog.jobbole.com/114331/', 'http://blog.jobbole.com/114329/', 'http://blog.jobbole.com/114327/', 'http://blog.jobbole.com/114324/', 'http://blog.jobbole.com/114321/', 'http://blog.jobbole.com/114319/', 'http://blog.jobbole.com/114311/', 'http://blog.jobbole.com/114308/', 'http://blog.jobbole.com/114303/', 
'http://blog.jobbole.com/114297/', 'http://blog.jobbole.com/114285/', 'http://blog.jobbole.com/114283/', 'http://blog.jobbole.com/114280/', 'http://blog.jobbole.com/114276/', 'http://blog.jobbole.com/114273/', 'http://blog.jobbole.com/114270/', 'http://blog.jobbole.com/114268/', 'http://blog.jobbole.com/114261/', 'http://blog.jobbole.com/114168/']
(2)获取翻页链接

1)页面分析:
页面分析获取翻页链接url
通过图片上面标记,容易看出,我们要获取的翻页url在class为next page-numbers的a标签的href属性中,中这里提供两种方法获取相应内容:
Xpath路径:

'//*[@id="archive"]/div[21]/a[4]/@href'

CSS选择器:

# 页面上查找发现,next 属性值是唯一的,
# 所以可以直接根据类名next来查找下一页的url。
".next::attr(href)"

2)shell下运行结果

# 我选择的是CSS选择器获取,一眼看出比较简单嘛
>>> response.css(".next::attr(href)").extract()[0]
'http://blog.jobbole.com/all-posts/page/2/'
3.在Pycharm下实操代码
(1)基础代码
# -*- coding: utf-8 -*-
import scrapy
import re

class JobboleSpider(scrapy.Spider):
    # 用于区别Spider,该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。
    name = 'jobbole'
    # 爬取页面域名范围
    allowed_domains = ['blog.jobbole.com']
    # 爬取起始页面
    start_urls = ['http://blog.jobbole.com']
(2)获取文章url下载和翻页下载代码
# 爬取页面所有文章url和翻页url
# 翻页下载
def parse(self, response):
    # 1.获取单页面文章url
    post_urls = response.xpath('//*[@id="archive"]/div/div[1]/a/@href').extract()
    # 2.下载文章url
    for post_url in post_urls:
        yield Request(url= parse.urljoin(response.url,post_url),callback= self.parse_detail)
    # 3.获取翻页url和翻页下载
    next_url = response.css(".next::attr(href)").extract()
    if next_url != []:
        next_url = next_url[0]
        yield Request(url= parse.urljoin(response.url,next_url),callback= self.parse)
(3)解析单篇文章信息
# 获取单篇文章详情信息
def parse_detail(self,response):
    # 文章标题
    title = response.css(".entry-header h1 ::text").extract()[0]

    # 发布日期
    data_r = response.css(".entry-meta-hide-on-mobile::text").extract()[0].strip()
    data_time = data_r.replace('·','').strip()

    # 文章分类
    article_type = response.css("p.entry-meta-hide-on-mobile a::text").extract()
    if article_type != []:
        article_type = ",".join(article_type)

    # 点赞数
    praise_number = response.css(".href-style.vote-post-up h10::text").extract()
    if praise_number != [] :
        praise_number = int(praise_number[0])
    else:
        praise_number = 0

    # 收藏数
    collection_str = response.css("span.btn-bluet-bigger:nth-child(2)::text").extract()[0]
    reg_02 = '.*?(\d+).*'
    collection_number = re.findall(reg_02, collection_str)
    if collection_number:
        collection_number = int(collection_number[0])
    else:
        collection_number = 0

    # 评论数
    comment_number = response.css("a[href='#article-comment'] span::text").extract()[0]
    comment_number = re.findall(reg_02, comment_number)
    if comment_number:
        comment_number = int(comment_number[0])
    else:
        comment_number = 0

    print("文章标题:"+title)
    print("发布日期:"+data_time)
    print("文章分类:"+article_type)
    print("点赞数:"+str(praise_number))
    print("收藏数:"+str(collection_number))
    print("评论数:"+str(comment_number))
    print("----------------------------------------")
(4)整合上面(1)、(2)、(3)后在pycharm下运行效果

我运行了差不多7-9秒,目测爬取了100条信息应该有
运行部分截图

文章标题:泪流满面的 11 个 Git 面试题
发布日期:2018/08/22
文章分类:IT技术,Git
点赞数:1
收藏数:9
评论数:0
----------------------------------------
文章标题:设计微服务的最佳实践
发布日期:2018/08/23
文章分类:IT技术,微服务
点赞数:1
收藏数:1
评论数:0
----------------------------------------
···
文章标题:如何自动唤醒和关闭 Linux
发布日期:2017/12/06
文章分类:IT技术,Linux
点赞数:1
收藏数:1
评论数:0
----------------------------------------
文章标题:他们是优秀的前端,所以这些后端工作也交给他们…
发布日期:2017/12/07
文章分类:职场, 11 评论 ,程序员
点赞数:3
收藏数:4
评论数:11
----------------------------------------

四、后言

通过本次学习,不知道大家有没有对Scrapy有多一点点了解嘿,通过本次学习我知道了如何把页面发送给Scrapy,让它帮忙下载,即使是几千条数据,也没有出现连接错误,同时知道了关键字yield的基本使用方法,我觉得最重要的是我们爬取的思路,以及在爬取过程中如何选取更加适合的匹配方法(目前我们已经讲了:正则、Xpath、CSS选择器)。
继续加油,下一节我们将讲解如何设计数据库来存储我们获取的数据,并利用items方法交给pipelines进行数据存储和查重。

欢迎大家关注微信公众号:极简XksA,获取Python/Java/前端等学习资源!
极简XksA

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简说Python

多多少少都是爱,感谢充电。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值