文档章节

Python scrapy爬虫爬取伯乐在线全部文章,并写入数据库

zhaobig
 zhaobig
发布于 2017/09/11 20:49
字数 1491
阅读 39
收藏 0
点赞 0
评论 0

伯乐在线爬虫项目目的及项目准备:

1.使用scrapy创建项目

2.创建爬虫,bole 域名 jobbole.com

3.Start_urls = [‘http://blog.jobbole.com/all-posts/’]

4.爬取所有页数的文章

5.文章列表页需要数据

a) 缩略图的地址

b) 详情url地址

6.详情页面要提取的数据

# 博客标题

    # 博客创建时间

    # 博客url

    # 将url经过md5加密生成id

    # 缩略图的地址

    # 图片保存路径  #这个属性考虑好在哪赋值

    # 点赞数

    # 收藏数

    # 评论数

    # 博客作者

# 博客标签

7.将图片下载,保存到imgs文件夹中

8.将爬取的所有数据存储到数据库

创建项目我们在cmd中进行创建,在开始之前我们要将数据库表以及其中字段创建好。


spider爬虫代码:

# -*- coding: utf-8 -*-
import scrapy
import re
# ..上级目录
from ..items import BoleItem
# .同级目录
from .tools import get_number,md5
# MVC  Model view controler
# 降低代码耦合性
# MVVC


# 做url地址的拼接,如果没有域名才会进行拼接
import urlparse
class BoleSpider(scrapy.Spider):
    name = 'bole'
    allowed_domains = ['jobbole.com']
    start_urls = ['http://blog.jobbole.com/all-posts/']

    def parse(self, response):
        # 获取每一页的文章url和图片url
        a_list = response.xpath(".//*[@id='archive']/div/div[1]/a")

        for a in a_list:
            # 获取博客详情页面url
            # 获取博客图片的url
            a_href = a.xpath("@href").extract_first('')
            img_src = a.xpath("img/@src").extract_first('')

            yield scrapy.Request(
                url=a_href,
                callback=self.parse_detail,
                meta={"img_src":img_src}
            )
        next_page = response.xpath("//a[@class='next page-numbers']/@href").extract_first('')
        if next_page:
            # 发送请求,请求下一页
            yield scrapy.Request(
                url=next_page
            )

    def parse_detail(self,response):
        # 博客详情地址
        blog_url = response.url
        # 图片url地址
        img_src = response.meta["img_src"]
        # 图片地址有可能不完整
        if img_src:
            # 1.拼接URL地址
            img_src = urlparse.urljoin('http://www.jobbole.com',img_src)
        else:
            img_src = ''

        # 博客标题
        title = response.xpath("//div[@class='entry-header']/h1/text()").extract_first('')
        # 博客发布时间
        blog_date = response.xpath("//p[@class='entry-meta-hide-on-mobile']/text()").extract_first('').strip().replace(u'·','').strip()
        # 所有的标签
        tags = response.xpath("//p[@class='entry-meta-hide-on-mobile']/a/text()").extract()
        # join 将列表中所有的字符串拼接,并以,隔开
        # split 将字符串根据某个字符进行分割,返回一个列表
        tags = ','.join(tags)
        # 点赞数
        like_count = response.xpath("//h10/text()").extract_first('')
        # 没有点赞设置为0
        if like_count:
            like_count = int(like_count)
        else:
            like_count = 0
        # 评论数
        comment_count = response.xpath("//a[@href='#article-comment']/span/text()").extract_first('')
        comment_count = get_number(comment_count)

        # 收藏数
        bookmark_count = response.xpath("//span[contains(@class,'bookmark-btn')]/text()").extract_first('')
        bookmark_count = get_number(bookmark_count)
        # blog_id
        # img_path
        # 创建Item对象
        item = BoleItem()
        item['blog_id'] = md5(response.url)
        item["title"] = title
        item["blog_url"] = blog_url
        # 将图片url放在列表中
        item["img_src"] = [img_src]
        item["blog_date"] = blog_date
        item["tags"] = tags
        item["like_count"] = like_count
        item["comment_count"] = comment_count
        item["bookmark_count"] = bookmark_count
        print title,blog_date,blog_url,img_src,like_count,comment_count,bookmark_count,tags
        yield item


创建工具包tools,优化代码,工具包tools代码:
import hashlib
# md5加密函数
def md5(str):
    import hashlib
    m = hashlib.md5()
    m.update(str)
    return m.hexdigest()

# 只要以后需要从字符串中匹配数字,就可以使用这个函数
import re
def get_number(str):
    # 正则
    pattern = re.compile(r'\d+')
    rs = re.search(pattern, str)
    if rs:
        count = int(rs.group())
    else:
        count = 0
    return count

 设置随机请求头,设置middlewares中内容
代码如下:
# 设置随机请求头
from fake_useragent import UserAgent
class RandomUAMiddleware(object):
    def __init__(self,crawler):
        super(RandomUAMiddleware, self).__init__()
        self.crawler = crawler
        self.ua = UserAgent()
    @classmethod
    def from_crawler(cls,crawler):
        return cls(crawler)
    # 处理请求函数
    def process_request(self,request,spider):
        # 随机产生请求头
        request.headers.setdefault('User-Agent',self.ua.random)

在item中创建数据模型类
class BoleItem(scrapy.Item):
    title = scrapy.Field()
    blog_url = scrapy.Field()
    img_src = scrapy.Field()
    blog_date = scrapy.Field()
    tags = scrapy.Field()
    like_count = scrapy.Field()
    comment_count = scrapy.Field()
    bookmark_count = scrapy.Field()
    img_path = scrapy.Field()
    blog_id = scrapy.Field()


写入数据库,我们使用异步写入,首先在setting文件中自己配置一些项目信息

# 数据库配置
MYSQL_HOST = '127.0.0.1'
MYSQL_PORT = 3306
MYSQL_USER = 'root'
MYSQL_PASSWD = '123456'
MYSQL_CHARSET = 'utf8'
MYSQL_DBNAME = 'jobbole'


然后设置pipelines,其中包含了我们写入数据库的代码,和下载图片的代码
代码如下:
from scrapy.http.request import  Request
class MyImagePipeline(ImagesPipeline):

    # 把当前的item处理完成之后,执行这个函数
    def item_completed(self, results, item, info):
        # 首先判断要下载的图片是否有完成信息
        if results:
            try:
                # 检测有有没有图片信息字典
                # 先取出列表中的元组,再从元组中取出字典
                img_dic = results[0][1]
                img_path = img_dic["path"]
            except Exception,e:
                print '------',e
                img_path = '没有图片路径'
        else:
            img_path = '没有图片信息'
        # 对item的img_path赋值
        item["img_path"] = 'imgs/'+img_path
        # 返回item
        return item

    # 当需要处理媒体文件时,会执行该函数
    def get_media_requests(self, item, info):

        # 获取图片的url地址
        for src in item['img_src']:

            return Request(
                url=src,
                meta={'item':item}
            )
        # return [Request(x) for x in item["img_src"], []]

    # 指定图片存放的路径
    def file_path(self, request, response=None, info=None):
        # 取出item
        item = request.meta["item"]
        # 取出图片url
        img_name = request.url.split('/')[-1]
        return img_name


# 异步写入数据库
from twisted.enterprise import adbapi
from MySQLdb import cursors

class MysqlTwistedPipeline(object):
    @classmethod
    # 这个函数会自动调用
    def from_settings(cls,settings):
        # 准备好连接数据库需要的参数
        db_params = dict(
            # 复制当前行Ctrl + d
            host = settings["MYSQL_HOST"],
            port = settings["MYSQL_PORT"],
            user = settings["MYSQL_USER"],
            passwd = settings["MYSQL_PASSWD"],
            charset = settings["MYSQL_CHARSET"],
            db = settings["MYSQL_DBNAME"],
            use_unicode = True,
            # 指定游标类型
            cursorclass=cursors.DictCursor
        )
        # 创建连接池
        # 1.要连接的名称  2.连接需要的参数
        db_pool = adbapi.ConnectionPool('MySQLdb',**db_params)
        # 返回当前类的对象,并且把db_pool赋值给该类的对象
        return cls(db_pool)

    def __init__(self,db_pool):
        # 赋值
        self.db_pool = db_pool

    # 处理item函数
    def process_item(self,item,spider):
        # 把要处理的事件进行异步处理
        # 1.要处理的事件函数
        # 2.事件函数需要的参数
        query = self.db_pool.runInteraction(self.do_insert,item)
        # 执行sql出现错误信息
        query.addErrback(self.handle_error,item,spider)
    # 错误的原因
    def handle_error(self,failure,item,spider):

        print failure

    # 处理插入数据库的操作
    # cursor该函数是连接数据库的函数,并且放在异步去执行,cursor执行sql语句
    def do_insert(self,cursor,item):
        # 1.准备sql语句
        sql = 'insert into bolejb(title,blog_url,img_src,blog_date,tags,like_count,comment_count,bookmark_count,img_path,blog_id)VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'
        # 2.用cursor游标执行sql
        cursor.execute(sql, (item["title"], item["blog_url"], item["img_src"][0], item["blog_date"], item["tags"], item["like_count"],item["comment_count"], item["bookmark_count"], item["img_path"],item["blog_id"]))





最后我们需要设置我们setting文件中的内容,将我们重写的中间件在setting中进一步设置

DOWNLOADER_MIDDLEWARES = {
   'BoleSpider.middlewares.RandomUAMiddleware': 1,
}

ITEM_PIPELINES = {
   'BoleSpider.pipelines.MyImagePipeline': 1,
   'BoleSpider.pipelines.MysqlTwistedPipeline': 2,
}
# 根据哪个属性下载图片
IMAGES_URLS_FIELD = 'img_src'
IMAGES_STORE = 'imgs'

为了方便调试,我们可以创建一个debug文件

from scrapy.cmdline import execute execute(['scrapy','crawl','bole'])



© 著作权归作者所有

共有 人打赏支持
zhaobig
粉丝 0
博文 5
码字总数 5529
作品 0
省直辖县级行政区划
高级爬虫(一):Scrapy爬虫框架的安装

Hi 小伙伴们差不多有半个月没有更新干货了,一直有点忙,而且这中间还有曲折过程,也就没有更新文章. 但今天无论如何也要更新一篇文章,接下来是爬虫高级篇重点讲解的地方! 最近会连载Scrap...

Python绿色通道 ⋅ 04/22 ⋅ 0

一个月入门Python爬虫,快速获取大规模数据

数据是创造和决策的原材料,高质量的数据都价值不菲。而利用爬虫,我们可以获取大量的价值数据,经分析可以发挥巨大的价值,比如: 豆瓣、知乎:爬取优质答案,筛选出各话题下热门内容,探索...

Python开发者 ⋅ 04/25 ⋅ 0

Python3爬虫视频学习教程

大家好哈,现在呢静觅博客已经两年多啦,可能大家过来更多看到的是爬虫方面的博文,首先非常感谢大家的支持,希望我的博文对大家有帮助! 最近,主要的任务就是开发性感美女图片大全,使用p...

yangjiyue0520 ⋅ 2017/11/18 ⋅ 0

Python Scrapy 爬虫(四):部署与运行

接上篇,在上篇中,我们已经在服务器上搭建好了 Python3 环境以及对应的 virtualenv 虚拟环境了。接下来,我们开始把代码部署到我们的服务器环境并运行。 在部署我们的代码到服务器前,我们来...

雨林_a1d6 ⋅ 06/01 ⋅ 0

[增强可拓展性]Scrapy博客爬虫

前言 最近赶毕业论文也是心力憔悴,现在写一篇文章谈谈我的毕业设计。 在最初学习Python的时候,爬虫是个不错的练手项目,但是几乎所有的爬虫教程都是教我们如何如何爬一个网站。 比如我写的...

3inchtime ⋅ 06/07 ⋅ 0

5.2 高富帅python-人工智能时代

小奈:其实你们写的代码好像有不同派系的? 大仁:你是说编程语言?我来介绍下吧,我们来看下GitHub(程序员同城交友、代码协作平台)的数据,看下各种编程语言 Pull Requst的数据, Javascr...

产品经理的技术课堂 ⋅ 05/11 ⋅ 0

[原创]手把手教你写网络爬虫(3):开源爬虫框架对比

原文出处:拓海 介绍 大家好!我们从今天开始学习开源爬虫框架Scrapy,如果你看过《手把手》系列的前两篇,那么今天的内容就非常容易理解了。细心的读者也许会有疑问,为什么不学出身名门的A...

拓海 ⋅ 04/28 ⋅ 0

5个python爬虫教材,让小白也有爬虫可写,含视频教程!

认识爬虫   网络爬虫,如果互联网是一张蜘蛛网,网络爬虫既是一个在此网上爬行的蜘蛛,爬了多少路程即获取到多少数据。 python写爬虫的优势   其实以上功能很多语言和工具都能做,但是用...

柯西带你学编程 ⋅ 06/12 ⋅ 0

利用Python寻找命中注定的另一半, 大家都觉得不可信, 毕竟都还没看这篇神级教程!

既然是Python程序员找美女,就要用python程序员的方法。 今天我们的目标是,爬社区的美女而且,我们又要用到新的姿势(雾)了scrapy爬虫框架~ 1scrapy原理 在写过几个爬虫程序之后,我们就知道...

柯西带你学编程 ⋅ 06/06 ⋅ 0

python3 scrapy爬取智联招聘存mongodb

写在前面,这次写智联招聘的爬虫是其次,主要的是通过智联招聘上的数据信息弄一个数据挖掘的小项目,这一篇主要是如何一气呵成的将智联招聘上的招聘信息给爬下来 (一)scrapy框架的使用 sc...

徐代龙 ⋅ 05/01 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JAVA RMI

什么是JAVA RMI Java RMI (Remote Method Invocation) 远程方法调用,能够让客户端像使用本地调用一样调用服务端 Java 虚拟机中的对象方法。RMI 是面向对象语言领域对 RPC (Remote Proced...

saulc ⋅ 8分钟前 ⋅ 0

Linux系统工程狮养成记

如今的社会,随着时代的发展,出现了很多职业,像电子类,计算机类的专业,出现了各种各样的工程师,有算法工程师,java工程师,前端工程师,后台工程师,Linux工程师,运维工程师等等,不同...

linux-tao ⋅ 18分钟前 ⋅ 0

进入编辑模式 vim命令模式 vim实践

1.

oschina130111 ⋅ 18分钟前 ⋅ 0

mysql用户管理、常用sql语句、mysql数据库备份恢复

1. mysql用户管理 mysql默认有一个root超级管理员账户,实际工作环境中不可能每个人都用此root权限,防止误操作、误删除,可以给单独的用户进行授权。 Mysql创建用户以及授权: grant all on...

laoba ⋅ 19分钟前 ⋅ 0

类型后面三个点(String...)和数组(String[])的区别

类型后面三个点(String…),是从Java 5开始,Java语言对方法参数支持一种新写法,叫可变长度参数列表,其语法就是类型后跟…,表示此处接受的参数为0到多个Object类型的对象,或者是一个Obj...

流氓兔- ⋅ 24分钟前 ⋅ 0

JEPLUS表格组件之表格合并——JEPLUS软件快速开发平台

JEPLUS表格组件之表格合并 我们在列表配置时会遇见这样的一种情况,需要对个人的数据进行统一化,对一些数据进行归类,这样展示出来美观又直观,在这篇笔记中我来给大家介绍下如何配置出来专...

JEPLUS ⋅ 26分钟前 ⋅ 0

golang 并发中全局唯一操作

package main// go 携程共享 数据// 加锁解锁操作// 同步锁import ("sync""fmt")// 创建Once结构var once = sync.Once{}func computed(data *int, lock *sync.Mut...

304158 ⋅ 26分钟前 ⋅ 0

Mobx入门之二:asynchronous actions

这一节主要看mobx怎么实现asynchronous actions 1 要实现的demo功能 输入地名,查询天气,利用openweathermap api 2 思想 observable观察数据:location地点、temperature温度 observer响应式...

pengqinmm ⋅ 29分钟前 ⋅ 0

【2018.0620学习笔记】【linux高级知识 13.4-13.6】

13.4 mysql用户管理 13.5 常用sql语句 13.6 mysql数据库备份恢复

lgsxp ⋅ 50分钟前 ⋅ 0

Java强弱引用示例

package jdk;import java.lang.ref.PhantomReference;import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference;import java.lang.ref.WeakReference;public ......

月下狼 ⋅ 56分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部