利用scrapy爬取简书文章并保存到数据库

这篇文章主要是介绍利用scrapy爬取简书IT专栏的文章,并把爬取结果保存到数据库中。所以实现这些功能的前提电脑中安装了scrapy,MySQL数据库,和一些爬虫的基本知识。代码我会详细介绍。如果有问题也可以给我留言。

简介

scrapy

官方文档的介绍是“Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。”我现在对它了解还不是很多,知道它的功能很强大,但还只会做一些简单的爬取。

MySQL数据库

MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言–结构化查询语言(SQL)进行数据库管理。

安装方法我在这里就赘述了,网上有很多方法。因为我安装scrapy的方法不是最简单的,所以我就不介绍我的方法了;至于MySQL,这个比较容易。安装好直接就可以使用了。

功能实现

scrapy部分

我们的目的是抓取简书@IT·互联网专题,网址是:

http://www.jianshu.com/c/V2CqjW

这个网址的确可以抓取到内容,但只是极少部分,在浏览的过程中还会继续加载内容,所以这个网址是不对的。我们必须获取它的真实网址才行。这就用到了抓包。

通过抓包我们获取到的真实网址是:

http://www.jianshu.com/c/V2CqjW?order_by=commented_at&page=1

应该已经注意到了,真正有用的是page,我们在抓取的时候只要改变页数就能实现多页抓取。

按下win+R,输入cmd运行终端,输入scrapy startproject jianshu等待scrapy自动生成文件,在jianshu->jianshu->spiders文件夹下创建jianshuspider.py文件。

jianshuspider.py代码部分:

from scrapy.spider import Spider
from jianshu.items import JianshuItem
class JianshuSpider(Spider):
    name = 'jianshu'
    box = []
    for num in range(120):
        pages = 'http://www.jianshu.com/c/V2CqjW?order_by=commented_at&page={0}'.format(num)
        box.append(pages)
    start_urls = box
    def parse(self, response):
        item = JianshuItem()
        articles = response.xpath("//ul[@class='note-list']/li")
        for article in articles:
            item['author'] = article.xpath('.//div[@class="name"]/a/text()').extract()[0]
            item['title'] = article.xpath('.//div[@class="content"]/a/text()').extract()[0]
            item['times'] = article.xpath('.//div[@class="name"]/span/@data-shared-at').extract()[0]
            url = article.xpath('.//div[@class="content"]/a/@href').extract()[0]
            item['url'] = 'http://www.jianshu.com' + url
            admire = article.xpath('.//div/div[2]/span[2]/text()').extract()
            item['admire'] = ''.join(admire)
            likes = article.xpath('.//div/div[2]/span[1]/text()').extract()
            item['likes'] = ''.join(likes)
            yield item

我来介绍一下这段代码。

name是以后运行爬虫的名字,start_urls是爬取的网站,是一个列表,因为我们要抓取很多页,所以我定义了一个空列表用来存放不同页数的网址。parse部分可以说就是用来把爬取到的内容传递给item。我们抓取了简书文章的作者、文章标题、创建的时间、文章的网址、赞赏和喜欢。

在筛选信息的过程中用到了xpath,其实只要多看看别人的代码,自己研究研究,很好理解的。jianshuspider.py这部分代码筛选出需要的结果后,我们就开始写items.py。

items.py代码部分:

import scrapy
class JianshuItem(scrapy.Item):
    title = scrapy.Field()
    author = scrapy.Field()
    times = scrapy.Field()
    url = scrapy.Field()
    admire = scrapy.Field()
    likes = scrapy.Field()

这部分代码就是对应的要抓取的内容。很好理解。正常情况下,在jianshu的文件夹下运行命令提示符,输入scrapy crawl jianshu
就可以看到运行结果了。因为我们要保存到数据库,所以还得继续完成代码。

MySQL部分

这部分用到了数据库的知识,安装好数据库以后,在数据库的终端登录以后,输入CREATE DATABASE jianshu;,然后输入USE jianshu;,在使用jianshu数据库后,所有的操作就都在这个数据库里了。在结束命令的时候一定要记得输入“;”分号。然后就是创建新表。输入:

CREATE TABLE articles (id BIGINT(5) NOT NULL AUTO_INCREMENT, title VARCHAR(100), author VARCHAR(100), times VARCHAR(100), url VARCHAR(100), admire VARCHAR(1000), likes VARCHAR(1000))

这样就创建好了表,如果输入无误的话输入DESCRIBE articles;就可以查看表的数据结构了。如图:

scrapy保存到数据库

创建好新表,我们就可以写pipelines.py的代码了。

pipelines.py代码部分:

import pymysql
def dbHandle():
    conn = pymysql.connect(
        host = "localhost",
        user = "root",
        passwd = "root",
        charset = "utf8",
        use_unicode = False
    )
    return conn
class JianshuPipline(object):
    def process_item(self,item,spider):
        dbObject = dbHandle()
        cursor = dbObject.cursor()
        cursor.execute("USE jianshu")
        sql = "INSERT INTO articals(author,title,times,url,admire,likes) VALUES(%s,%s,%s,%s,%s,%s)"
        try:
            cursor.execute(sql,(item['author'],item['title'],item['times'],item['url'],item['admire'],item['like']))
            cursor.connection.commit()
        except BaseException as e:
            print("错误在这里>>>>>>>>>>>>>",e,"<<<<<<<<<<<<<错误在这里")
            dbObject.rollback()
        return item

代码分为两部分,第一部分用来连接数据库,第二部分用来用来向数据库传入数据。

如果这段代码不是太明白可以先看这部分代码,Python操作数据库的代码:

#导入pymysql模块
import pymysql
#连接数据库
conn = pymysql.connect(host='127.0.0.1', user='root', passwd='root', db='music')
cur = conn.cursor()
#输入使用数据库和查询信息的命令,操作类似在cmd中的输入
cur.execute("USE music")
#插入数据(pages是数据库music下的表)
cur.execute("INSERT INTO pages(title,content) VALUES('449454051','http://m2.music.126.net/GvSlxgdwVCKelv3gFaw9pg==/18641120138988064.mp3')")
cur.connection.commit()
#更新数据
cur.execute("SELECT * FROM pages")
print("获取全部信息\n",cur.fetchall())
#关闭数据库
cur.close()
conn.close()

先导入pymysql库,然后定义函数,用来存放数据库信息。下边的JianshuPipline在创建文件时自动生成。我们只要添加往数据库导入信息的代码就可以了。

我们还需要改一改settings.py中的代码,把下边的代码添加和修改一下就行了。

settings.py代码:

ROBOTSTXT_OBEY = False #True 修改为 False

#添加请求头
DEFAULT_REQUEST_HEADERS = {
'accept': 'image/webp,*/*;q=0.8',
'accept-language': 'zh-CN,zh;q=0.8',
'referer': 'https://www.jianshu.com/',
'user-agent': 'Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36',
}

#连接数据库
ITEM_PIPELINES = {
'jianshu.pipelines.JianshuPipline': 300,
}

这样就算大功告成了。查看数据库,如图:

总结

在迷迷糊糊看完上边的教程之后我们总结一下。

scrapy组件的作用

Item 对象是种简单的容器,保存了爬取到得数据。其提供了类似于词典(dictionary-like)的API以及用于声明可用字段的简单语法。

Spider 类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取 item)。换句话说,Spider 就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。

当 Item 在 Spider 中被收集之后,它将会被传递到 Item Pipeline,一些组件会按照一定的顺序执行对 Item 的处理。

详情查看官方文档:http://scrapy-chs.readthedocs.io/zh_CN/1.0/intro/install.html

数据库

在创建数据库和新表的过程中一定要仔细,避免错输和漏输,在出现问题的时候一定要认真阅读提示的错误信息。如果字太小的话可以这么设置。我电脑的操作系统是Win10。如图:

把字体调的大一点看起来就轻松许多。数据库命令如果不是很懂可以自行查阅资料,因为我也在学习中,先不介绍了太多。

与本文相关的链接

1.http://scrapy-chs.readthedocs.io/zh_CN/1.0/intro/install.html
2.https://www.mysql.com/
3.http://www.jianshu.com/c/V2CqjW
4.格外感谢这篇教程,受此启发:Scrapy入门教程之写入数据库

如果在操作过程中遇到问题欢迎留言,也可查看:https://alpha87.github.io/

推荐阅读更多精彩内容