scrapy 详细实例-爬取百度贴吧数据并保存到文件和和数据库中

本文详细介绍如何使用Scrapy框架爬取百度贴吧数据,包括项目搭建、爬虫编写、数据提取及存储过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。使用框架进行数据的爬取那,可以省去好多力气,如不需要自己去下载页面、数据处理我们也不用自己去写。我们只需要关注数据的爬取规则就行,scrapy在python数据爬取框架中数据比较流行的,那么今天就用scrapy进行百度贴吧-黑中介贴吧数据的爬取。别问我为啥爬取黑中介吧的,因为我个人经历过一番。。咳咳咳,要抓住重点,咱们还是来讲怎么爬数据吧(赃官猛于虎!)。

注意:你需要自己先安装python和scrapy框架哦~

1、创建项目

scrapy startproject 自定义项目名

scrapy startproject baidutieba

该命令将会创建包含下列内容的 sqc_scapy的目录:

baidutieba/
    scrapy.cfg
    baidutieba/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            ...
scrapy.cfg: 项目的配置文件
baidutieba/: 该项目的python模块。之后您将在此加入代码。
baidutieba/items.py: 项目中的item文件.
baidutieba/pipelines.py: 项目中的pipelines文件.
baidutieba/settings.py: 项目的设置文件.
baidutieba/spiders/: 放置spider代码的目录.

2、创建爬虫文件

我们要编写爬虫,首先是创建一个Spider
我们在baidutieba/spiders/目录下创建一个文件MySpider.py  。文件包含一个MySpider类,它必须继承scrapy.Spider类。同时它必须定义一下三个属性:
1、-name: 用于区别Spider。 该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。 
2、-start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。 
3、-parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(responsedata),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。

创建完成后MySpider.py的代码如下

#引入文件
import scrapy

class MySpider(scrapy.Spider):
    #用于区别Spider
    name = "MySpider"
    #允许访问的域
    allowed_domains = []
    #爬取的地址
    start_urls = []
    #爬取方法
    def parse(self, response):
        pass

3、定义Item

爬取的主要目标就是从非结构性的数据源提取结构性数据,例如网页。 Scrapy提供 Item 类来满足这样的需求。
Item 对象是种简单的容器,保存了爬取到得数据。 其提供了 类似于词典(dictionary-like) 的API以及用于声明可用字段的简单语法。

来,咱们先确定要爬取的数据元素

大家可以看到我们在工程目录下可以看到一个items文件,我们可以更改这个文件或者创建一个新的文件来定义我们的item。
这里,我们在同一层创建一个新的item文件Tbitems.py:

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

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy

class Tbitem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    #内容
	user_info = scrapy.Field()
	title = scrapy.Field()
	url = scrapy.Field()
	short_content = scrapy.Field()
	imgs = scrapy.Field()


如上:咱们建立了Tbitems容器来保存抓取的信息,user_info 对应发帖人信息  ,title帖子标题,url帖子详情地址,short_content帖子的简短介绍,imgs帖子的图片

常用方法如下:

#定义一个item
info= Tbitem()
#赋值
info['title'] = "语文"
#取值
info['title']
info.get('title')
#获取全部键
info.keys()
#获取全部值
info.items()

4、完善我的爬虫主程序1:

# coding=utf-8
# 
import scrapy
from baidutieba.Tbitems import Tbitem


class MySpider(scrapy.Spider):
	name = "MySpider"
	allowed_domains = ['tieba.baidu.com']
	start_urls = ['https://tieba.baidu.com/f?ie=utf-8&kw=%E9%BB%91%E4%B8%AD%E4%BB%8B&fr=search']

	def parse(self, response):
		item = Tbitem()
		boxs = response.xpath("//li[contains(@class,'j_thread_list')]")
		for box in boxs:
			item['user_info'] = box.xpath('./@data-field').extract()[0];
			item['title'] = box.xpath(".//div[contains(@class,'threadlist_title')]/a/text()").extract()[0];
			item['url'] = box.xpath(".//div[contains(@class,'threadlist_title')]/a/@href").extract()[0];
			item['short_content'] = box.xpath(".//div[contains(@class,'threadlist_abs')]/text()").extract()[0];
			if box.xpath('.//img/@src'):
				item['imgs'] = box.xpath('.//img/@src').extract()[0];
			else:
				item['imgs'] =[]
			yield item
注:这里用到了xpath方式来获取页面信息,这里不做过多介绍,可以参考网上的xpath教程来自己学习


上面这个是利用谷歌浏览器扩展组件XPath-Helper进行的调试  组件地址:XPath-Helper_v2.0.2,当然谷歌浏览器自带了获取元素xpath路径的方法如下:



大家注意爬取的部分在MySpider类的parse()方法中进行。 
parse()方法负责处理response并返回处理的数据

该方法及其他的Request回调函数必须返回一个包含 Request 及(或) Item 的可迭代的对象(yield item 具体介绍请看  彻底理解Python中的yield

(在scrapy框架中,可以使用多种选择器来寻找信息,这里使用的是xpath,同时我们也可以使用BeautifulSoup,lxml等扩展来选择,而且框架本身还提供了一套自己的机制来帮助用户获取信息,就是Selectors。 因为本文只是为了入门所以不做过多解释。)

cd进入工程文件夹,然后运行命令行

scrapy crawl 自己定义的spidername

scrapy crawl MySpider

看以看到我们已经运行成功了 ,获取到了数据。不过那大家运行可以看到我们只爬了一页的数据,那么我们想将分页数据全部爬取那该如何做?

def parse(self, response):
		item = Tbitem()
		boxs = response.xpath("//li[contains(@class,'j_thread_list')]")
		for box in boxs:
			item['user_info'] = box.xpath('./@data-field').extract()[0];
			item['title'] = box.xpath(".//div[contains(@class,'threadlist_title')]/a/text()").extract()[0];
			item['url'] = box.xpath(".//div[contains(@class,'threadlist_title')]/a/@href").extract()[0];
			item['short_content'] = box.xpath(".//div[contains(@class,'threadlist_abs')]/text()").extract()[0];
			if box.xpath('.//img/@src'):
				item['imgs'] = box.xpath('.//img/@src').extract()[0];
			else:
				item['imgs'] =[]
			yield item

		#url跟进开始
		#获取下一页的url信息
		url = response.xpath('//*[@id="frs_list_pager"]/a[10]/@href').extract()
		
		if url :
			page = 'https:' + url[0]
			#返回url
        	yield scrapy.Request(page, callback=self.parse)
        #url跟进结束


可以看到url跟进 和for同级  也就是说 for循环完成后(即本页面数据抓取完成后)进行下一页的爬取,获取到下一页 按钮的地址 然后作为一个Request进行了可迭代的数据返回这样就可以进行分页数据的爬取了


5、将爬取的数据进行保存

当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。
每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
以下是item pipeline的一些典型应用:
(1)清理HTML数据
2)验证爬取的数据(检查item包含某些字段)
3)查重(并丢弃)
4)将爬取结果保存到文件或数据库中

1、将数据保存到文件里

首先那我们在项目目录下 pipelines.py同级目录建立我们的BaidutiebaPipeline.py文件

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

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
#设置系统默认字符集
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import codecs
import json
from logging import log



class JsonWithEncodingPipeline(object):
    '''保存到文件中对应的class
       1、在settings.py文件中配置
       2、在自己实现的爬虫类中yield item,会自动执行'''    
    def __init__(self):
        self.file = codecs.open('info.json', 'w', encoding='utf-8')#保存为json文件
    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"#转为json的
        self.file.write(line)#写入文件中
        return item
    def spider_closed(self, spider):#爬虫结束时关闭文件
        self.file.close()

那么这我们的数据保存到文件里的Item Pipeline就写好了,那么接下来我们想要用它就需要先注册自己的Pipeline:

在同级目录下有一个settings.py 打开文件找到ITEM_PIPELINES 注册我们的Pipeline

格式:项目目录.Pipeline文件名.Pipeline中的类名

后面int型的参数是标示执行的优先级,范围1~1000,越小越先执行

# Configure item pipelines
# See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
	'baidutieba.BaidutiebaPipeline.JsonWithEncodingPipeline': 300,
}
那么我们再运行、

scrapy crawl MySpider


2、将数据保存到数据库中

同样在settings.py中添加咱们的数据库保存Pipeline,并且在其中设置数据库的配置如下:

# Configure item pipelines
# See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
	'baidutieba.BaidutiebaPipeline.JsonWithEncodingPipeline': 300,
	'baidutieba.BaidutiebaPipeline.WebcrawlerScrapyPipeline': 300,
}


# MySql 数据库链接操作
MYSQL_HOST = '127.0.0.1'
MYSQL_DBNAME = 'test'         #数据库名字,请修改
MYSQL_USER = 'homestead'             #数据库账号,请修改 
MYSQL_PASSWD = 'secret'         #数据库密码,请修改
MYSQL_PORT = 3306               #数据库端口,在dbhelper中使用



修改BaidutiebaPipeline.py文件

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

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
#设置系统默认字符集
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

from twisted.enterprise import adbapi
import MySQLdb
import MySQLdb.cursors
import codecs
import json
from logging import log



class JsonWithEncodingPipeline(object):
    '''保存到文件中对应的class
       1、在settings.py文件中配置
       2、在自己实现的爬虫类中yield item,会自动执行'''    
    def __init__(self):
        self.file = codecs.open('info.json', 'w', encoding='utf-8')#保存为json文件
    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"#转为json的
        self.file.write(line)#写入文件中
        return item
    def spider_closed(self, spider):#爬虫结束时关闭文件
        self.file.close()

class WebcrawlerScrapyPipeline(object):
    '''保存到数据库中对应的class
       1、在settings.py文件中配置
       2、在自己实现的爬虫类中yield item,会自动执行'''    

    def __init__(self,dbpool):
        self.dbpool=dbpool
        ''' 这里注释中采用写死在代码中的方式连接线程池,可以从settings配置文件中读取,更加灵活
            self.dbpool=adbapi.ConnectionPool('MySQLdb',
                                          host='127.0.0.1',
                                          db='crawlpicturesdb',
                                          user='root',
                                          passwd='123456',
                                          cursorclass=MySQLdb.cursors.DictCursor,
                                          charset='utf8',
                                          use_unicode=False)'''        
        
    @classmethod
    def from_settings(cls,settings):
        '''1、@classmethod声明一个类方法,而对于平常我们见到的则叫做实例方法。 
           2、类方法的第一个参数cls(class的缩写,指这个类本身),而实例方法的第一个参数是self,表示该类的一个实例
           3、可以通过类来调用,就像C.f(),相当于java中的静态方法'''
        dbparams=dict(
            host=settings['MYSQL_HOST'],#读取settings中的配置
            db=settings['MYSQL_DBNAME'],
            user=settings['MYSQL_USER'],
            passwd=settings['MYSQL_PASSWD'],
            charset='utf8',#编码要加上,否则可能出现中文乱码问题
            cursorclass=MySQLdb.cursors.DictCursor,
            use_unicode=False,
        )
        dbpool=adbapi.ConnectionPool('MySQLdb',**dbparams)#**表示将字典扩展为关键字参数,相当于host=xxx,db=yyy....
        return cls(dbpool)#相当于dbpool付给了这个类,self中可以得到

    #pipeline默认调用
    def process_item(self, item, spider):
        query=self.dbpool.runInteraction(self._conditional_insert,item)#调用插入的方法
        query.addErrback(self._handle_error,item,spider)#调用异常处理方法
        return item
    
    #写入数据库中
    def _conditional_insert(self,tx,item):
        #print item['name']
        sql="insert into test(name,url) values(%s,%s)"
        print 3333333333333333333333
        print item["title"]
        params=(item["title"].encode('utf-8'),item["url"])
        tx.execute(sql,params)
    
    #错误处理方法
    def _handle_error(self, failue, item, spider):
        print '--------------database operation exception!!-----------------'
        print '-------------------------------------------------------------'
        print failue



 

这个是我给大家的一个入门的示例,如果大家有问题可以给我留言或者私信。另外由于百度贴吧的升级,可能程序抓取规则会要做相应的调整,但是主体不会变哦,大家需要自己调整下程序哦

程序完成时间:2017.7.18

程序代码

使用 Scrapy 爬取古诗文数据存储到 MySQL 数据库中,可以按照以下步骤进行: 1. **安装必要的库**: 首先,确保你已经安装了 Scrapy MySQL 的 Python 库。可以使用 pip 进行安装: ```bash pip install scrapy pymysql ``` 2. **创建 Scrapy 项目**: 使用 Scrapy 创建一个新的项目: ```bash scrapy startproject poetry_spider ``` 3. **定义 Item**: 在 `poetry_spider/items.py` 中定义你要爬取的字段,例如标题、作者内容: ```python import scrapy class PoetrySpiderItem(scrapy.Item): title = scrapy.Field() author = scrapy.Field() content = scrapy.Field() ``` 4. **编写爬虫**: 在 `poetry_spider/spiders` 目录下创建一个新的爬虫文件,例如 `poetry_spider.py`: ```python import scrapy from poetry_spider.items import PoetrySpiderItem class PoetrySpider(scrapy.Spider): name = 'poetry' start_urls = ['http://www.example.com/poetry'] def parse(self, response): poems = response.css('div.poem') for poem in poems: item = PoetrySpiderItem() item['title'] = poem.css('h2::text').get() item['author'] = poem.css('p.author::text').get() item['content'] = poem.css('div.content::text').get() yield item next_page = response.css('a.next::attr(href)').get() if next_page: yield response.follow(next_page, self.parse) ``` 5. **配置 MySQL**: 在 `poetry_spider/settings.py` 中配置数据库连接信息: ```python import pymysql pymysql.install_as_MySQLdb() DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'poetry_db', 'USER': 'your_username', 'PASSWORD': 'your_password', 'HOST': 'localhost', 'PORT': '3306', } } ``` 6. **编写 Pipeline**: 在 `poetry_spider/pipelines.py` 中编写数据存储逻辑: ```python import pymysql class PoetrySpiderPipeline(object): def __init__(self): self.connection = pymysql.connect( host='localhost', user='your_username', password='your_password', db='poetry_db', charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor ) self.cursor = self.connection.cursor() def process_item(self, item, spider): sql = "INSERT INTO poems (title, author, content) VALUES (%s, %s, %s)" self.cursor.execute(sql, (item['title'], item['author'], item['content'])) self.connection.commit() return item def close_spider(self, spider): self.cursor.close() self.connection.close() ``` 7. **启用 Pipeline**: 在 `poetry_spider/settings.py` 中启用刚刚编写的 Pipeline: ```python ITEM_PIPELINES = { 'poetry_spider.pipelines.PoetrySpiderPipeline': 300, } ``` 8. **运行爬虫**: 最后,运行爬虫: ```bash scrapy crawl poetry ``` 这样,Scrapy 就会开始爬取古诗文数据存储到 MySQL 数据库中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值