赞
踩
摘要:
如果我们把互联网比作一张大的蜘蛛网,数据便是存放于蜘蛛网的各个节点;而爬虫就是一只小蜘蛛,沿着网络抓取自己的猎物(数据)爬虫指的是:向网站发起请求,获取资源后分析并提取有用数据的程序;从技术层面来说就是 通过程序模拟浏览器请求站点的行为,把站点返回的HTML代码/JSON数据/二进制数据(图片、视频) 爬到本地,进而提取自己需要的数据,存放起来使用;
友情提示:
本文所有关于 python 的基本代码都是基于 python3.7 的,不同 python 版本之间会有些许差异,但不影响我们对 整体的把握和了解。
由于 本文的源代码实现依赖于python源代码,所以阅读本文需要读者了解关python的基本语法,关于python基本语法 请移步菜鸟教程 http://www.runoob.com/python/python-tutorial.html,以及还有mysql的基本操作,需要读者有基本的了解
Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛。
框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便。
我们在项目中主要用到了如下加黑的部分
Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,
Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器)
Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.
Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。
Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)
引用链接:https://www.jianshu.com/p/306e03c618cf
下载地址:https://www.python.org/downloads/windows/
本文项目环境:window10
python版本: Windows x86-64 executable installer
下载地址:https://www.jetbrains.com/pycharm/download/#section=windows,并选择window版本安装
有一点 不要在pycharm上直接安装 scrapy 不知道因为什么一直失败,莫名的尴尬
我们直接在 C:\Users\jie\AppData\Local\Programs\Python\Python37\Scripts 这个scripts目录下打开cmd安装
1、如果失败考虑安装whl格式的包:
如果安装whl格式包则需要安装wheel库,安装方法:pip install wheel
2、由于scrapy依赖twiste,先要安装twiste:
下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/
在网页中搜索twisted找到对应的whl包并下载:Twisted‑18.4.0‑cp37‑cp37m‑win_amd64.whl
根据Python版本选择合适的包,名称中间的cp37是python3.7的意思,amd64是python的位数)
下载完成后使用cmd命令打开windows的命令行窗口,进入whl包所在的文件夹执行如下命令:pip install [whl]
[whl]是whl包的名字,即:pip install Twisted‑18.4.0‑cp36‑cp36m‑win_amd64.whl
3、scrapy依赖lxml包,安装lxml: pip install lxml
4、下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/ 在网页中搜索scrapy下载scrapy的whl包
Scrapy‑1.5.0‑py2.py3‑none‑any.whl
下载完成后使用cmd命令打开windows的命令行窗口,进入whl包所在的文件夹执行如下命令:pip install [whl]
[whl]是whl包的名字,即:pip install Scrapy‑1.5.0‑py2.py3‑none‑any.whl
这样安装一定成功
然后使用 pycharm 记得先在 file -》setting 中更改为你的 python 环境
这样环境就算是安装完成了
5.1创建一个新项目 demo1
5.2 代建 scrapy 框架
创建 Tengxun 在 编辑器底部栏的 terminal 终端 中输入
scrapy startproject Tengxun
5.3 分析我们要做什么操作,以如下几点
- 新建项目 (scrapy startproject xxx):新建一个新的爬虫项目
- 明确目标 (编写items.py):明确你想要抓取的目标
- 制作爬虫 (spiders/xxspider.py):制作爬虫开始爬取网页
- 存储内容 (pipelines.py):设计管道存储爬取内容
5.4 修改setting的代码 ,在setting 文件夹下加入如下 code
-
- # 函数的执行顺序,序号越小,优先级越高
- ITEM_PIPELINES = {
- 'HupuSpider.pipelines.HupuspiderPipeline': 1,
- 'HupuSpider.pipelines.HupuImagesPipeline': 2,
- }
- LOG_LEVEL='DEBUG'
- ROBOTSTXT_OBEY = True
5.5 创建 item
- import scrapy
-
- class HupuspiderItem(scrapy.Item): (注意这里的类名你需要根据自己的命名做更改)
- # 明星名称
- starname = scrapy.Field()
- # 明星url
- starurl = scrapy.Field()
- # 简介内容
- content=scrapy.Field()
- # 简介标题
- contenttitle=scrapy.Field()
- # 拍的电影图片
- imageurl=scrapy.Field()
5.6 爬取我们想要获得数据的网页,进而分析
创建如下文件
- import scrapy
-
- class demoSpider(scrapy.Spider):
- name = "dmoz"
- allowed_domains = ["dmoz.org"]
- start_urls = [
- "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
- "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
- ]
-
- def parse(self, response):
- filename = response.url.split("/")[-2] + '.html'
- with open(filename, 'wb') as f:
- f.write(response.body)
获取到html 然后 我们在对其进行分析
5.7 编写我们的逻辑代码 (刚刚创建的文件中)
- # -*- coding: utf-8 -*-
- from HupuSpider.items import HupuspiderItem
- import scrapy
- import os
-
- class NbaNewsSpider(scrapy.Spider):
- name = 'tengxun'
- # allowed_domains = ['v.qq.com/x/hotlist/search/?channel=556']
- start_urls = ['https://v.qq.com/x/hotlist/search/?channel=556']
- def parse(self, response):
- # 抓取响应体
- # filename = response.url.split("/")[-5] + '.html'
- # print(response.extract())
- # with open(filename, 'wb') as f:
- # f.write(response.body)
-
- # 明星排行榜单
- result = response.xpath('/html/body/div[3]/div[1]/div[1]/div[2]/ul/li/div[1]/a')
- # print(result.extract())
- # 榜单明星名字
- startman = result.xpath('.//text()').extract()
- # print(startman)
-
- # 榜单明星具体信息地址
- startmanurl = result.xpath('.//@href').extract()
- # print(startmanurl)
- # 存放 bean 数据
- items = []
- # 创建明星目录
- for i in range(0,len(startman)):
- item = HupuspiderItem()
-
- # 指定存储目录+明星名字
- teamFilename="./今日明星/"+startman[i]
-
- # 如果目录不存在,则创建目录
- if (not os.path.exists(teamFilename)):
- os.makedirs(teamFilename)
-
- item['starname']=startman[i]
- item['starurl']=startmanurl[i]
-
- items.append(item)
- # print(items)
-
- # #发送每个明星的url的Request请求,得到Response连同包含meta数据
- # # 一同交给回调函数 second_parse 方法处理
- for item in items:
- for i in range(1,2):
- # tempurl = item['starurl'].replace('.html','')
- # teamurl = tempurl + '-' + str(i) + '.html'
- yield scrapy.Request(url=item['starurl'], meta={'meta_1': item}, callback=self.second_parse)
-
- # 对每支球队的url进行爬取
- def second_parse(self,response):
- # items = 0
- # 提取每次Response的meta数据(就是上个函数保存下来的)
- item = response.meta['meta_1']
- # 获得明星个人简介
- temp = response.css('.desc_text').xpath('string(.)').extract()[0]
- item['content'] = temp
- # print(temp)
- # 明星个人电影图片
- temp = "";
- imaurl = response.xpath('/html/body/div[2]/div[2]/div[1]/div[2]/div[2]/div[2]/div[1]/div[1]/ul/li/a/img/@src').extract()
- for i in range(0, len(imaurl)):
- temp = temp+","+imaurl[i]
- item['imageurl'] = temp
- item['contenttitle'] = item['starname']
- yield item
5.8 在 pipelines 文件中编写item 的处理(含有创建 txt 文件,图片下载处理,上传信息到数据库)
- # -*- coding: utf-8 -*-
- from scrapy.pipelines.images import ImagesPipeline
- from scrapy.utils.project import get_project_settings
- import scrapy
- import shutil
- import pymysql
- import os
-
- class HupuspiderPipeline(object):
- def process_item(self, item, spider):
- # 明星名字作为简介txt的名字
- filename = item['contenttitle']
- filename += ".txt"
-
- # 个人简介放到个人相对应的文件夹中
- savepath='./今日明星'+'/'+item['starname']+'/'+filename
- fp = open(savepath, 'w', encoding='utf-8')
- fp.write(item['content'])
- fp.close()
-
- host = '127.0.0.1'
- user = 'root'
- psd = 'root'
- db = "python"
- c = "utf8"
- port = 3306
- # 数据库连接
- con = pymysql.connect(host=host, user=user, passwd=psd, db=db, charset=c, port=port)
- # 数据库游标
- cue = con.cursor()
- print("mysql connect succes") # 测试语句,这在程序执行时非常有效的理解程序是否执行到这一步
- try:
- cue.execute("insert into news (name,content) values(%s,%s)",
- [item['starname'], item['content']])
- print("insert success") # 测试语句
- except Exception as e:
- print('Insert error:', e)
- con.rollback()
- else:
- con.commit()
- con.close()
-
- return item
-
- class HupuImagesPipeline(ImagesPipeline):
- # 重写ImagesPipeline类的此方法
- # 发送图片下载请求
- def get_media_requests(self, item, info):
- image_url = item["imageurl"]
- str = image_url.split(',')
- for i in range(1, len(str)-1):
- yield scrapy.Request("http:"+str[i])
-
- # 重写item_completed方法
- # 将下载的文件保存到不同的目录中
- def item_completed(self, results, item, info):
- # 从项目设置文件中导入图片下载路径
- IMAGES_STORE = get_project_settings().get("IMAGES_STORE")
- # 固定写法,获取图片路径,同时判断这个路径是否正确,如果正确,
- for i in range(0,len(results)):
- os.rename(IMAGES_STORE + '/' + results[i][1]['path'], IMAGES_STORE + '/' + item['starname'] + str(i) + '.jpg')
- shutil.move(IMAGES_STORE + '/' + item['starname'] + str(i) +'.jpg', './今日明星' + '/' + item['starname'])
-
- def __del__(self):
- IMAGES_STORE = get_project_settings().get("IMAGES_STORE")
- # 完成后删除整个full目录
- shutil.rmtree(IMAGES_STORE + '/' + 'full')
- shutil.rmtree(IMAGES_STORE)
5.8.1 创建 txt 代码
- filename = item['contenttitle']
- filename += ".txt"
-
- # 个人简介放到个人相对应的文件夹中
- savepath='./今日明星'+'/'+item['starname']+'/'+filename
- fp = open(savepath, 'w', encoding='utf-8')
- fp.write(item['content'])
- fp.close()
5.8.2 图片下载的代码
- # 重写ImagesPipeline类的此方法
- # 发送图片下载请求
- def get_media_requests(self, item, info):
- image_url = item["imageurl"]
- str = image_url.split(',')
- for i in range(1, len(str)-1):
- yield scrapy.Request("http:"+str[i])
-
- # 重写item_completed方法
- # 将下载的文件保存到不同的目录中
- def item_completed(self, results, item, info):
- # 从项目设置文件中导入图片下载路径
- IMAGES_STORE = get_project_settings().get("IMAGES_STORE")
- # 固定写法,获取图片路径,同时判断这个路径是否正确,如果正确,
- for i in range(0,len(results)):
- os.rename(IMAGES_STORE + '/' + results[i][1]['path'], IMAGES_STORE + '/' + item['starname'] + str(i) + '.jpg')
- shutil.move(IMAGES_STORE + '/' + item['starname'] + str(i) +'.jpg', './今日明星' + '/' + item['starname'])
-
- def __del__(self):
- IMAGES_STORE = get_project_settings().get("IMAGES_STORE")
- # 完成后删除整个full目录
- shutil.rmtree(IMAGES_STORE + '/' + 'full')
- shutil.rmtree(IMAGES_STORE)
5.8.3 数据上传到 mysql
- host = '127.0.0.1'
- user = 'root'
- psd = 'root'
- db = "python"
- c = "utf8"
- port = 3306
- # 数据库连接
- con = pymysql.connect(host=host, user=user, passwd=psd, db=db, charset=c, port=port)
- # 数据库游标
- cue = con.cursor()
- print("mysql connect succes") # 测试语句,这在程序执行时非常有效的理解程序是否执行到这一步
- try:
- cue.execute("insert into news (name,content) values(%s,%s)",
- [item['starname'], item['content']])
- print("insert success") # 测试语句
- except Exception as e:
- print('Insert error:', e)
- con.rollback()
- else:
- con.commit()
- con.close()
6.1
6.2
参考
http://www.runoob.com/python/python-tutorial.html
https://scrapy-chs.readthedocs.io/zh_CN/1.0/intro/overview.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。