前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Scrapy框架爬取伯乐在线全部文章并写入数据库案例

Scrapy框架爬取伯乐在线全部文章并写入数据库案例

作者头像
菲宇
发布2019-06-13 11:55:51
6530
发布2019-06-13 11:55:51
举报
文章被收录于专栏:菲宇菲宇

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

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']) 原文:https://blog.csdn.net/zhaobig/article/details/77936444

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年05月06日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档