爬虫进阶之Scrapy(三) 使用scrapy某新闻网并存到数据库-张柏沛IT博客

正文内容

爬虫进阶之Scrapy(三) 使用scrapy某新闻网并存到数据库

栏目:Python 发布时间:2019-12-06 16:31 浏览量:225

本节我们通过爬取一个新闻网站的新闻来介绍scrapy的pipeline,以及如何在pipeline中将爬取到的数据写入到数据库中。

首先是我们要爬取的内容是

https://www.chinanews.com

这个网站首页的所有文章的标题和内容。


数据表字段只要3个:

id,title和content


接下来正式开始:

创建scrapy项目

scrapy startproject qqnews


为啥起名叫qqnews呢,因为本来打算爬取腾讯网的新闻,后来有改主意了,哈哈哈哈,不过不用在意这些细节。


首先我们要先定义容器:

qqnews/items.py 内容如下

# -*- coding: utf-8 -*-

import scrapy


class QqnewsItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    content = scrapy.Field()

容器中只有两个字段,title和content


接下来我们正式编写spider:

qqnews/spiders 目录中创建一个qqnews_spider.py文件

内容如下:

# coding = utf-8

#取出https://news.qq.com首页的所有文章的文章详情页的标题,内容,和文章来源,并存入到数据库中
import scrapy
from qqnews.items import QqnewsItem

class QqnewsSpider(scrapy.Spider):
    name="qqnews"
    start_urls=["https://www.chinanews.com"]
    allowed_domains=["www.chinanews.com"]

    def parse(self,res):
        #获取首页所有详情页的链接
        urls=res.xpath(r"//a[re:test(@href,'//www.chinanews.com/[a-zA-z]+/\d+/\d+-\d+/\d+\.s?html')]/@href").extract()
        for url in urls:
            if url.find("http") == -1:
                url="https:"+url
            # print(url)
            yield scrapy.Request(url,callback=self.parse_news)  #Request会请求获取到的文章链接,callback=self.parse_news表示将请求到的页面内容传给parse_news方法
        

    def parse_news(self,news):
        #获取标题和内容
        qqnew_item=QqnewsItem()
        qqnew_item['title']=news.xpath("//div[@class='content']/h1/text()").extract_first()
        qqnew_item['content']='\n'.join(news.xpath("//div[@class='left_zw']/p/text()").extract())

        yield qqnew_item



蜘蛛启动后执行的第一个方法就是parse方法,所以,请不要修改parse方法的方法名,其他方法都可以自定义名称,但parse方法名请不要动。

在parse方法中,定义了获取所有首页文章a标签的xpath规则,在xpath中也是支持使用正则的。

上面parse方法负责获取所有的文章链接,并请求这些链接并将请求到的页面源代码内容传给parse_news方法;而parse_news方法则负责获取文章详情页的标题和文章正文并存到item容器中,并返回。


parse_news是将文章都爬取到了,但是我们要控制它将文章存到数据库中,这里就要使用到pipeline

它位于scrapy项目目录的pipelines.py

这个文件的作用是可以对抓取到的内容进行处理,比如你已经抓取到了内容和标题,现在你想做一下事情:
a.对数据进行过滤,或者对数据的格式进行调整
b.将数据存到数据库中
这些都可以在这个文件中进行


当然在pipeline中不仅仅可以做数据存储,还可以做很多事情,比如数据的修改。

PS:pipelines.py默认是不会起作用的,如果想要起作用,要在settings.py将这个的注释去掉
还有像如果你要讲数据存到数据库中的话,数据库的配置信息也是写到这个文件中的。


所以接下来我们要修改setting.py文件

在setting.py添加数据库配置

DB_CONFIG={
   "host":"127.0.0.1",
   "user":"root",
   "password":"你自己的数据库密码",
   "database":"test",
   "charset":"utf8"
}


在setting.py开启pipeline:

ITEM_PIPELINES = {
   'qqnews.pipelines.QqnewsPipeline': 300,
}


写法是这样的:

'项目目录名.pipelines文件名.想开启的pipeline的类名':执行顺序       #执行顺序是个数字,数字越小,越先执行;pipelines文件可以不只一个,可以自定义,但是里面的写法要遵循原pipeline的写法


配置了setting之后,在pipelines.py进行数据库操作:

# -*- coding: utf-8 -*-

import json,pymysql

#导入settings.py中的配置信息
# from scrapy.conf import settings

class QqnewsPipeline(object):
    def __init__(self):
        self.data=[]

    #连接数据库
    def open_spider(self,spider):
        # 连接
        self.conn = pymysql.connect(**spider.settings.get('DB_CONFIG'))
        # 创建光标
        self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)

    def close_spider(self,spider):
        #一次性将所有的数据插入
        sql="insert into news values (%s,%s,%s)"
        self.cursor.executemany(sql,self.data)

        self.cursor.close()
        self.conn.close()

    def process_item(self, item, spider):
        self.data.append((None,item['title'],item['content']))


spider.settings.get("DB_CONF")可以获取到你在setting中定义的数据库配置


PS:parse_news()一定要将qqnew_item容器返回,否则pipelines是获取不到容器中的数据的,到时候存到数据库的内容会为空。

如果想要在xpath中使用正则,就要像上面那样写,re:test()表示是使用re.test()方法,还可以re:match(); 


open_spider/close_spider/process_item 这三个方法是pipeline类中固定的方法,继承自父类;我们只需重写这三个方法即可;

这三个方触发的时机是:

open_spider 在蜘蛛启动时触发,所以从爬取开始到结束只执行一次。

close_spider 在蜘蛛关闭时触发,所以从爬取开始到结束只执行一次。

process_item 在蜘蛛返回item容器的时候触发,所以基本上是爬取一个详情页就出发一次。


上面的脚本都写好之后,只需在cmd执行

scrapy crawl dmoz

即可开始爬取

​​​​​​​

要注意的是:

Scrapy是会对链接自动去重的,不需要担心scrapy会爬取到重复的链接

Scrapy是多线程爬取,爬取的速度会比自己写的简单爬虫要快


如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > 爬虫进阶之Scrapy(三) 使用scrapy某新闻网并存到数据库

热门推荐
推荐新闻