基于Scrapy爬取伯乐在线网站(进阶版)

news/2024/5/20 22:20:40/文章来源:https://blog.csdn.net/xiaosa_kun/article/details/84868401

标题中的英文首字母大写比较规范,但在python实际使用中均为小写。
爬取伯乐在线网站所有文章的详情页面

1.网页持久化

1.1 新建爬虫工程

新建爬虫工程命令:scrapy startproject BoleSave2


10345471-d2bedb87ff4a547f.png
image.png

进入爬虫工程目录命令:cd BoleSave2
新建爬虫文件命令:scrapy genspider save blog.jobbole.com

1.2 编辑save.py文件

网页持久化只需要编辑爬虫文件就可以,下面是save.py文件的代码。
第13行dirName变量的值可以设置网页文件保存的位置,例如:
dirName = "d:/saveWebPage"将网页文件保存在D盘的saveWebPage文件夹中。
可以根据个人情况进行修改,不能将其设置为工程所在文件夹,因为Pycharm对工程内大量新文件进行索引会导致卡顿。

import scrapy
import os
import redef reFind(pattern,sourceStr,nth=1):if len(re.findall(pattern,sourceStr)) >= nth:return re.findall(pattern,sourceStr)[nth-1]else:return 1def saveWebPage(response,id,prefix):# 持久化目录页面dirName = "d:/saveWebPage2"if not os.path.isdir(dirName):os.mkdir(dirName)html = response.textfileName = "%s%05d.html" %(prefix,id)filePath = "%s/%s" %(dirName, fileName)with open(filePath, 'w', encoding="utf-8") as file:file.write(html)print("网页持久化保存为%s文件夹中的%s文件" %(dirName,fileName))class SaveSpider(scrapy.Spider):name = 'save'allowed_domains = ['blog.jobbole.com']start_urls = ['http://blog.jobbole.com/all-posts/']def parse(self, response):pageNum = response.xpath("//a[@class='page-numbers']/text()")[-1].extract()for i in range(1, int(pageNum) + 1):url = "http://blog.jobbole.com/all-posts/page/{}/".format(i)yield scrapy.Request(url, callback=self.parse1)def parse1(self, response):page_id = int(reFind("\d+", response.url))saveWebPage(response,page_id,'directory')#获得详情页面的链接,并调用下一级解析函数article_list = response.xpath("//div[@class='post floated-thumb']")count = 0for article in article_list:url = article.xpath("div[@class='post-meta']/p/a[1]/@href").extract_first()count += 1article_id = (page_id - 1) * 20 + countyield scrapy.Request(url,self.parse2,meta={'id':article_id})def parse2(self, response):saveWebPage(response,response.meta['id'],'detail')

1.3 编辑settings.py文件

改变并发请求数量,取消变量CONCURRENT_REQUESTS的注释,并改变值为96。
CONCURRENT_REQUESTS = 96

1.4 运行结果

运行命令:scrapy crawl save
559个目录页面,11172个详情页面,两种页面相加共有11731个页面。
而网页持久化保存的文件个数也是11731个,说明已经完成页面持久化。


10345471-3d305eb8edf0df28.png
image.png

从下图中可以看出开始时间与结束时间相差12分钟,则11731个页面持久化耗时12分钟。
持久化速度:977页/分,16.29页/秒


10345471-096b44aa42b3ba00.png
image.png

2.解析伯乐在线文章详情页面

已经把11731个网页文件打包成一个压缩文件,下载链接: https://pan.baidu.com/s/19MDHdwrqrSRTEgVWA9fMzg 密码: x7nk

2.1 新建爬虫工程

新建爬虫工程命令:scrapy startproject BoleParse2
进入爬虫工程目录命令:cd BoleParse2
新建爬虫文件命令:scrapy genspider parse blog.jobbole.com

2.2 在Pycharm中导入工程

导入工程的按钮位置如下图所示:


10345471-3751fab90d8c0495.png
image.png

选中工程文件夹,然后点击OK,如下图所示:


10345471-0e35d3eb0b07290b.png
image.png

工程文件夹的结构如下图所示:
10345471-61b870cbad8daa8e.png
image.png

2.3 编写items.py文件

共有12个字段,文章识别码id、标题title、发布时间publishTime、分类category、摘要digest、图片链接imgUrl、详情链接detailUrl、原文出处originalSource、内容content、点赞数favourNumber、收藏数collectNumber、评论数commentNumber。

import scrapy
from scrapy import Fieldclass Boleparse2Item(scrapy.Item):id = Field()title = Field()publishTime = Field()category = Field()digest = Field()imgUrl = Field()detailUrl = Field()originalSource = Field()content = Field()favourNumber = Field()collectNumber = Field()commentNumber = Field()

2.4 编写parse.py文件

parse函数解析目录页面,得到7个字段的值添加进item中,并通过response携带meta传递给下一级解析函数。
parse2函数解析详情页面,通过item = response.meta['item']得到已经解析一部分内容的item,再对网页解析得到剩余的5个字段,最后yield item将item传给管道进行处理。

注意:修改第13行变量dirName的值

import scrapy
import re
from ..items import Boleparse2Itemdef reFind(pattern,sourceStr,nth=1):if len(re.findall(pattern,sourceStr)) >= nth:return re.findall(pattern,sourceStr)[nth-1]else:return ''class ArticleSpider(scrapy.Spider):name = 'parse'dirName = "E:/saveWebPage2"start_urls = []for i in range(1,560):fileName = "directory%05d.html" %ifilePath = "file:///%s/%s" %(dirName,fileName)start_urls.append(filePath)def parse(self, response):def find(xpath, pNode=response):if len(pNode.xpath(xpath)):return pNode.xpath(xpath).extract()[0]else:return ''article_list = response.xpath("//div[@class='post floated-thumb']")pattern = self.dirName + "/directory(\d+).html"page_id_str = reFind(pattern,response.url)page_id = int(page_id_str)count = 0for article in article_list:count += 1item = Boleparse2Item()item['id'] = (page_id - 1) * 20 + countitem['title'] = find("div[@class='post-meta']/p[1]/a/@title",article)pTagStr = find("div[@class='post-meta']/p",article)item['publishTime'] = re.search("\d+/\d+/\d+",pTagStr).group(0)item['category'] = find("div[@class='post-meta']/p/a[2]/text()",article)item['digest'] = find("div[@class='post-meta']/span/p/text()",article)item['imgUrl'] = find("div[@class='post-thumb']/a/img/@src",article)item['detailUrl'] = find("div[@class='post-meta']/p/a[1]/@href", article)fileName = "detail%05d.html" %item['id']nextUrl = "file:///%s/%s" %(self.dirName,fileName)yield scrapy.Request(nextUrl,callback=self.parse1,meta={'item':item})def parse1(self, response):def find(xpath, pNode=response):if len(pNode.xpath(xpath)):return pNode.xpath(xpath).extract()[0]else:return ''item = response.meta['item']item['originalSource'] = find("//div[@class='copyright-area']""/a[@target='_blank']/@href")item['content'] = find("//div[@class='entry']")item['favourNumber'] = find("//h10/text()")item['collectNumber'] = find("//div[@class='post-adds']"\"/span[2]/text()").strip("收藏").strip()commentStr = find("//a[@href='#article-comment']/span")item['commentNumber'] = reFind("(\d+)\s评论",commentStr)yield item

2.5 编写pipelines.py文件

采用数据库连接池提高往数据库中插入数据的效率。
下面代码有2个地方要修改:1.数据库名;2.连接数据库的密码。
设置数据库编码方式,default charset=utf8mb4创建表默认编码为utf8mb4,因为插入字符可能是4个字节编码。
item['content'] = my_b64encode(item['content'])将网页内容进行base64编码防止发生异常。

from twisted.enterprise import adbapi
import pymysql
import time
import os
import base64def my_b64encode(content):byteStr = content.encode("utf-8")encodeStr = base64.b64encode(byteStr)return encodeStr.decode("utf-8")class Boleparse2Pipeline(object):def __init__(self):self.params = dict(dbapiName='pymysql',cursorclass=pymysql.cursors.DictCursor,host='localhost',db='bole',user='root',passwd='...your password',charset='utf8mb4',)self.tableName = "article_details"self.dbpool = adbapi.ConnectionPool(**self.params)self.startTime = time.time()self.dbpool.runInteraction(self.createTable)def createTable(self, cursor):drop_sql = "drop table if exists %s" %self.tableNamecursor.execute(drop_sql)create_sql = "create table %s(id int primary key," \"title varchar(200),publishtime varchar(30)," \"category varchar(30),digest text," \"imgUrl varchar(200),detailUrl varchar(200)," \"originalSource varchar(500),content mediumtext," \"favourNumber varchar(20)," \"collectNumber varchar(20)," \"commentNumber varchar(20)) " \"default charset = utf8mb4" %self.tableNamecursor.execute(create_sql)self.dbpool.connect().commit()def process_item(self, item, spider):self.dbpool.runInteraction(self.insert, item)return itemdef insert(self, cursor, item):try:if len(item['imgUrl']) >= 200:item.pop('imgUrl')item['content'] = my_b64encode(item['content'])fieldStr = ','.join(['`%s`' % k for k in item.keys()])valuesStr = ','.join(['"%s"' % v for v in item.values()])insert_sql = "insert into %s(%s) values(%s)"\% (self.tableName,fieldStr, valuesStr)cursor.execute(insert_sql)print("往mysql数据库中插入第%d条数据成功" %item['id'])except Exception as e:if not os.path.isdir("Log"):os.mkdir("Log")filePath = "Log/" + time.strftime('%Y-%m-%d-%H-%M.log')with open(filePath, 'a+') as file:datetime = time.strftime('%Y-%m-%d %H:%M:%S')logStr = "%s log:插入第%d条数据发生异常\nreason:%s\n"file.write(logStr % (datetime, item['id'], str(e)))def close_spider(self, spider):print("程序总共运行%.2f秒" % (time.time() - self.startTime))

2.6 编写settings.py文件

BOT_NAME = 'BoleParse2'
SPIDER_MODULES = ['BoleParse2.spiders']
NEWSPIDER_MODULE = 'BoleParse2.spiders'
ROBOTSTXT_OBEY = False
CONCURRENT_REQUESTS = 96
CONCURRENT_ITEMS = 200
ITEM_PIPELINES = {'BoleParse2.pipelines.Boleparse2Pipeline': 300,
}

2.7 运行结果

运行命令:scrapy crawl parse


10345471-010424f549311a80.png
image.png

从上图可以看出,插入数据总共需要花费420秒,即25条/秒,1558条/分。


10345471-cda7921508425f70.png
image.png

从上图可以看出插入数据总共使用硬盘容量679.5M,条数共11172条,成功插入每一条数据。

3.查找插入异常原因

mysql中查看字符集命令:show variables like "character%"

10345471-4e37b5852323f127.png
image.png

content中有组合字符\"导致发生SQL syntax error
10345471-c0d273620dd142f3.png
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_774224.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用腾讯云服务器发布网站

参考资料 百度百科-域名绑定服务器IP 百度百科-网站绑定IP Django官方推荐教程-NginxGunicorn部署Django CSDN-NginxGunicorn部署Django CSDN-nginxgunicorn部署django项目 用到的工具软件 FlashFXP:用于像服务器传输文件Navicat:MySQL数据库管理软件…

幼儿linux教程,新增20多种小游戏 - 专为3岁儿童设计的Ubuntu 10.10应用体验_Linux教程_Linux公社-Linux系统门户网站...

新增20多种小游戏也许是开发者觉得儿童最喜欢的就是游戏了,所以集成了20多种游戏,包括:贪吃蛇、俄罗斯方块、对对碰、国际象棋、黑白棋以及十几种逻辑等。游戏其中,在逻辑游戏中,有一款gbralny头脑难题游戏头脑训练游戏…

珍藏多年的技术资源搜索网站——程序员必备

程序员经常需要找一些技术书籍和相关文档,但是通过百度查找往往都是需要各种积分才能够下载,笔者平时的学习中积累几个搜索工具网站,基本上所有需要的技术文档,经典书籍,学习资料,学习视频等等都可以在下列…

网站加服务器翻倍,如何短期内让网站收录翻倍或者翻数倍?

虽然我们千方百计地想产生高质量的原创内容,但如果搜索引擎不收录,那么一切都是无用功。因为只有被搜索引擎收录的页面,才对网站具有投票的能力,所以,从这个角度来讲,大型网站的SEO策略的核心其实是在做“收…

分析电商网站图片放大的实现原理

先分析下大致原理&#xff0c;放大原理实际上是一张正常图片&#xff0c;再加上一张放大n倍图片&#xff0c;根据鼠标在正常图片上的位置&#xff0c;再将位置乘n倍&#xff0c;定位到放大图片&#xff0c;显示。先来看看效果 <!DOCTYPE html> <html lang"en&…

Java面试送分题:php+mysql动态网站开发教案

天下码农&#xff0c;多为CV&#xff01;你是否每天还在增删改查&#xff1f;性能优化让你手足无措&#xff1f;看这里&#xff01;技术大牛带你分分钟完爆性能优化&#xff01;&#xff01;&#xff01; Java性能权威指南淘宝千万并发性能优化实战&#xff01;理论结合实战&am…

Github标星5.3K,大型网站演变中的负载均衡场景

享学课堂特邀作者&#xff1a;老顾 转载请声明出处&#xff01; 前言 我们小伙伴们是不是经常看到网上一些集群、高可用、高并发、负载均衡等关键词&#xff0c;有很多种方案、以及应用场景中都有相关的介绍。今天老顾就带着大家一起看一下&#xff0c;一整套大型网站会有哪些…

推荐一个SpringBoot + Vue + MyBatis 音乐网站项目

项目说明 本音乐网站的客户端和管理端使用 VUE 框架来实现&#xff0c;服务端使用 Spring Boot MyBatis 来实现&#xff0c;数据库使用了 MySQL。 项目功能 音乐播放 用户登录注册 用户信息编辑、头像修改 歌曲、歌单搜索 歌单打分 歌单、歌曲评论 歌单列表、歌手列表…

阿里P7好友说,要想成为Java大佬,就多逛逛国外的这几个技术网站

这是我为高级Java开发人员准备的网站的集合。 这些网站提供新闻&#xff0c;常见问题或访谈问题的答案&#xff0c;精彩的讲座等。质量是好的网站的关键因素。我认为它们都具有最高的质量。 在下文中&#xff0c;我还将分享如何使用这些网站进行学习或娱乐。您可能认为某些站…

四、wordpress主题美化 网站logo制作

1、查找一个合适的字体 参考网站&#xff1a;字体天下 2、下载字体生成工具 fontmin 3、生成logo 打开软件 fontmin &#xff0c;拖入下载的字体&#xff0c;生成logo 4、引入字体 编辑主题下的文件 header.php&#xff0c;引入字体文件xxx.css <link rel"st…

本地tomcat可以运行web项目,但是发布到服务器上面不能访问web网站404错误

问题描述&#xff1a; 本地tomcat运行起来可以在本地浏览器访问web页面&#xff0c;但是打包到服务器发现tomcat虽然加载了这个文件&#xff0c;但是并不能打开网页访问。出现404错误。 分析&#xff1a; 404错误一般是找不到目标页面&#xff0c;服务器没有响应&#xff0c…

在腾讯云部署一个自己的网站 问题总结

步骤一览 首先得有一个html文件名叫index.html&#xff0c;必须叫这个&#xff0c;作为我们现成的网页&#xff0c;网页可以参考我之前的博客【传送门】 然后得有一台云服务器&#xff0c;这里选择腾讯云作为&#xff0c;因为学生有优惠&#xff1a;【优惠链接传送门】 购买…

浏览器访问网站的过程

假设你用一个全新的浏览器&#xff08;第一次启动的那种&#xff09;&#xff0c;访问百度&#xff08;http://www.baidu.com/&#xff09;&#xff0c;在你敲入网址并按下回车之后&#xff0c;将会发生以下神奇的事情&#xff1a; 浏览器先尝试从Host文件中获取http://www.bai…

django admin建站

------------setting.py配置--------------------------- TIME_ZONE Asia/Shanghai ------时区 # Language code for this installation. All choices can be found here: # http://www.i18nguy.com/unicode/language-identifiers.html LANGUAGE_CODE utf8 --…

LaTex数学公式语法网站

LaTex数学公式语法网站 https://latex.codecogs.com/eqneditor/editor.php 比如想要查找小于等于号&#xff0c;就直接选中这个符号&#xff0c;然后填充框里面就会有相应的语法&#xff0c;把这个语法复制到md文件里面的数学公式里面去就可以了。这里提示一下&#xff0c;md语…

md代码渲染网站

这是一个md代码渲染网站&#xff0c;很多微信公众号上分享的代码渲染的就是这个网站来的&#xff0c;如下图。 https://carbon.now.sh/

为什么网站要禁用ip登录_为什么要使用 DDoS 高防 IP

为什么要使用 DDoS 高防 IP一、未使用高防之前&#xff1a;ECS 能防护的流量一般在 500M 左右&#xff0c;一旦攻击流量超过这个值&#xff0c;则ECS 被攻击的 IP 地址将进入黑洞&#xff0c;最长 24 小时无法访问&#xff0c;所以这种攻击会对企业的利益造成很大损失1、DDOS 防…

怎么给自己的网站弄ip地址_广东怎么建立自己的网站_百度排名-无忧云快推

广东无忧云网络科技有限公司为您详细解读XzMLCf广东怎么建立自己的网站的相关知识与详情&#xff0c; seo优化工做要分步推进&#xff0c;针对优化内容停止细分类&#xff0c;该推广哪方面的必需心中有数&#xff0c;做到投入和产出成比&#xff0c;才气让顾客合意。&…

魔众题库系统 v6.2.0 页面SEO优化,系统升级调整

魔众题库系统采用PHPMysql架构,是一款对SEO非常友好、功能全面、安全稳定、支持多终端展示并且使用起来极其简单的在线题库管理系统。 魔众题库系统发布v6.2.0版本&#xff0c;新功能和Bug修复累计15项&#xff0c;页面SEO优化&#xff0c;系统升级调整。 2021年12月07日魔众题…