好友
阅读权限10
听众
最后登录1970-1-1
|
ZJL丶
发表于 2020-6-29 17:49
本帖最后由 ZJL丶 于 2020-6-29 18:02 编辑
一、 scrapy框架简介:
1. 引擎(Scrapy)- 用来处理整个系统的数据流处理, 触发事务(框架核心)
2. 调度器(Scheduler)- 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
3. 下载器(Downloader)- 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
4. 爬虫(Spiders)- 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
5. 项目管道(Pipeline)- 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据
二、 代码构建流程:
1)通过startproject参数创建一个scrapy项目
[Asm] 纯文本查看 复制代码 scrapy startproject item_name
2)创建spider爬虫文件(注意域的范围不要带https://等东西,只爬到一页,因为这个问题我找了好久)
[Asm] 纯文本查看 复制代码 scrapy genspider name "movie.douban.com"
3)编写主爬虫文件(/spiders/douban.py),这里边代码是负责干活的
[Asm] 纯文本查看 复制代码 import scrapy
from study.items import StudyItem
class DoubanSpider(scrapy.Spider):
# 定义唯一标识区分爬虫,系统自动生成
name = 'douban'
# 定义域爬取范围
allowed_domains = ['movie.douban.com']
# 定义要爬取的网站
baseurl = 'https://movie.douban.com/top250?start='
# 定义偏移值
offset = 0
# 定义起始的url,系统自动生成,但是需要我们改动进行字符串拼接,方便爬取多页
start_urls = [baseurl + str(offset)]
def parse(self, response):
# xpath为response中的方法,可以将xpath表达式直接作用于该函数中
# 思路:爬取任何东西要先获取它变成一个整体(标签),然后一条一条爬取里边信息构建出一个列表
# 例如:[movie_name,movie_link,star,quote]这是一个标签里获取的一条电影信息
# 提醒:这个地方不要想着爬取整个网页然后在区分。
# 例如:[name,name,name,name][link,link,link,link][star,star,star,star] ......
moive_node = response.xpath("//div[@class='item']/div[@class='info']")
# 获取moive_node里每一条电影信息(每个页面会有25个movie_node)
for movie in moive_node:
# 通过xpth获取每个节点的单条电影信息的内容:
# xpath函数返回的为列表,列表中存放的数据为Selector类型的数据,所以返回给我们的是一个对象而不是我们想要的数据
# 我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。
# 影片名称
movie_name = movie.xpath("./div[@class='hd']/a/span[@class='title'][1]/text()").extract()
# 影片连接
movie_link = movie.xpath("./div[@class='hd']/a/@href").extract()
# 影评评分
star = movie.xpath("./div[@class='bd']/div[@class='star']/span[@class='rating_num']/text()").extract()
# 影片引言
quote = movie.xpath("./div[@class='bd']/p[@class='quote']/span[@class='inq']/text()").extract()
# 部分影片没有引言,所以要做判断处理
if quote:
quote = quote[0]
else:
quote = ""
# 将解析到的数据封装至items对象中
item = StudyItem()
# 下面是提取字典中的数据(值)
item['movie_name'] = movie_name[0]
item['movie_link'] = movie_link[0]
item['star'] = star[0]
# 此处注意不要写[0],因为上边判断的时候已经提取了第一个元素如果在取[0]只能取到第一个数字
item['quote'] = quote
# 提交item到管道文件(pipelines.py)
yield item
# 此处的if应该在for循环外面
# 如果写在for循环里的话就表示每提取一条信息就执行一下if
# 写在外边的话就是当前页面所有信息提取完了再执行下面代码
# 通过页面url分析我们得知最后一页是225但是不能大于等于哦!
if self.offset < 225:
# 通过分析得知步进值为25
self.offset += 25
# 拼接url获取下一页的url
url = self.baseurl + str(self.offset)
# 通过回调函数callback将下一页的url提交给parse再进行电影信息解析提取
# 也就是for循环25次,if的代码执行一次
# 注:for里面相当于每个电影,if里面相当于每一页
yield scrapy.Request(url, callback=self.parse)
# 注意:此方案不是最佳方案因为判断条件我写死了(因为豆瓣top250不会进行数据更新,最多250个)
# 思路1:可以通过下一页标签用xpath提取下一页,进行url拼接,然后再传递url
# 需要判断什么情况下下一页是灰色,例如://a[[url=home.php?mod=space&uid=341152]@Class[/url] = next] == 0的时候
# 还要注意第一页的上一页也是灰色,所以判断要满足某两个条件才行
# 思路2: 可以通过获取当前网站的总页数来进行数据爬取
4)既然爬虫文件已经获取到数据了,下一步我们就要处理spider返回的item数据(比如存储到json,mysql等等)
[Asm] 纯文本查看 复制代码 # Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
# 导入我们需要的包json,mysql
from itemadapter import ItemAdapter
import pymysql
import json
class StudyPipeline(object):
# 构造方法
def __init__(self):
self.f = None # 定义一个文件描述符属性
# 下列都是在重写父类的方法:
# 开始爬虫时,执行一次
def open_spider(self, spider):
print('爬虫开始')
# 打开一个json文件用于接收json方法写入的数据
self.f = open('douban.json', 'w', encoding='utf-8')
# 专门处理item对象
# 因为该方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中。
def process_item(self, item, spider):
# 将jsondumps方法获取的数据赋值给content
# 为什么将item转换成字典呢,因为这个item返回的值是scrapy特有的存储,python是不识别的
content = json.dumps(dict(item), ensure_ascii=False)+",\n"
self.f.write(content)
# 传递到下一个被执行的管道类,一定要返回item不然就会出错
return item
# 关闭爬虫
def close_spider(self, spider):
print('爬虫结束')
self.f.close()
# 管道文件中的一个管道类对应的是讲数据存储到一种平台
# 爬虫文件提交的item只会给管道文件中第一个被执行的管道类接受
# process_item的return item表示item传递到下一个被执行的管道类
# 将数据存储到数据库
class mysqlPipeline(object):
# pymysql插入数据简单用法
# 1. 连接connect = pymysql.connect("各种配置")
# 2. 创建游标 cursor = connect.cursor()
# 3. 执行sql语句 cursor.execute("sql")
# 4. 提交 connect.commit()
# 5. 关闭游标 cursor.close
# 6. 关闭数据库 connect.close
# 注意:56顺序不可颠倒!
# 构造方法
def __init__(self):
self.conn = None # 定义一个文件描述符属性
self.cursor = None
self.num = 0
# 下列都是在重写父类的方法:
# 开始爬虫时,执行一次
def open_spider(self, spider):
# 首先初始化构建一个建表sql
sql = '''
create table movie
(
movie_name varchar(500) ,
movie_link varchar(500) ,
star varchar(500),
quote varchar(500)
)
'''
# 连接mysql数据库
# 注:此处的配置建议写在setting配置中
self.conn = pymysql.connect(
host='192.168.0.157', # IP地址
port=3306, user='root', # 端口,账号
password='123456', # 密码
database='movie_top250', # 数据库名字
charset='utf8') # 字符集
cursor = self.conn.cursor() # 建立游标
cursor.execute(sql) # execute方法执行sql语句
self.conn.commit() # commit方法提交一个执行语句(只有插入和更新才需要哦)
print('爬虫数据库开始')# print在python里需要加()
# 专门处理item对象
# 因为该方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中。
def process_item(self, item, spider):
# 为了方便理解,这里将item返回的数据赋值给下边插入语句使用
movie_name = item['movie_name']
movie_link = item['movie_link']
star = item['star']
quote = item['quote']
# 执行sql前要建立一个游标,在上边方法已经连接数据库了所以这里不需要重连
self.cursor = self.conn.cursor()
# 进行mysql的异常捕获
try:
# 插入数据时候一定要对应好行和列
# 下方%s格式化字符串可以用format,自行测试
self.cursor.execute('''
insert into movie
values(%s,%s,%s,%s)''', (movie_name, movie_link, star, quote))
self.conn.commit() # 提交上方的插入sql
except Exception as e:
print(e)
self.conn.rollback() # 回滚
return item
# 关闭游标,关闭数据库连接
def close_spider(self, spider):
self.cursor.close()
self.conn.close()
print('爬虫数据库结束')
5)最后当然就是编写配置文件了setting.py(开启管道配置文件)注意要把robots协议关掉或者注释
[Asm] 纯文本查看 复制代码 BOT_NAME = 'study'
SPIDER_MODULES = ['study.spiders']
NEWSPIDER_MODULE = 'study.spiders'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
ITEM_PIPELINES = {
'study.pipelines.StudyPipeline': 300,
'study.pipelines.mysqlPipeline': 320,
}
最后分享小白一个xpath工具(xpath helper)google的插件,如图:
xpath-helper.zip
(131.21 KB, 下载次数: 118)
某盘: 链接:https://pan.baidu.com/s/14PUti26iAgb3zp43TZnV3w 提取码:92u6
纯手打求兄弟们点个赞!!!
|
-
ctrl+shift 用鼠标指哪里就会自动出xpath语句
免费评分
-
查看全部评分
|