课程设计要用到爬虫,稍微回顾下,Scrapy的爬虫四步走....只是简单的Scrapy,什么分布式爬虫啥的,感觉以后再说了....不谈了...
1、创建项目
cmd >> scrapy startproject douban## scrapy startproject project_name
cmd >> cd douban/douban/spiders
cmd >> scrapy genspider douban_spider movie.douban.com## scrapy genspider spider_text_name start_url
Scrapy包含上图几个部件:
1、Scrapy Engine
引擎负责控制数据流在系统中所有组件中流动,并在相应动作发生时触发事件。
2、Scheduler
调度器从引擎接受request并将他们入队,以便之后引擎请求他们时提供给引擎;简单的说就是调度队列,same as 操作系统中的调度队列.......
3、Downloader
下载器负责获取页面数据并提供给引擎,而后提供给spider。
4、Spiders
Spider是Scrapy用户编写用于分析response并提取item(即获取到的item)或额外跟进的URL的类。 每个spider负责处理一个特定(或一些)网站。
5、Item Pipeline
Item Pipeline负责处理被spider提取出来的item。典型的处理有清理、 验证及持久化(例如存取到数据库中)。
6、Downloader middlewares
下载器中间件是在引擎及下载器之间的specific hook,处理Downloader传递给引擎的response。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。
7、Spider middlewares
Spider中间件是在引擎及Spider之间的specific hook,处理spider的输入(response)和输出(items及requests)。 其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。
scrapy.cfg
: 项目的配置文件;project_modul/
: 该项目的python模块。之后您将在此加入代码;project_modul/items.py
: 项目中的item文件;project_modul/pipelines.py
: 项目中的pipelines文件;project_modul/settings.py
: 项目的设置文件;project_modul/spiders/
: 放置spider代码的目录;
2、明确目标
即了解你要哪些数据 ——>>> item.py
class DoubanItem(scrapy.Item):
#序号
serial_number = scrapy.Field()
#电影名称
movie_name = scrapy.Field()
#介绍
introduce = scrapy.Field()
#星级
star = scrapy.Field()
#描述
describe = scrapy.Field()熟悉Django的朋友一定会注意到Scrapy Item定义方式与Django Models很类似, 不过没有那么多不同的字段类型(Field type),更为简单。
3、爬虫文件的编写 ——>>> spiders [folders]
Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。
能够获取两类数据,一种就是纯数据,比如Title啥的,另外一种数据就是可递归的数据,即数据多的时候有好几页数据,里面的第二页,第几页就是可递归的链接数据
以初始的URL初始化Request,并设置回调函数。 当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数。
spider中初始的request是通过调用 start_requests() 来获取的。 start_requests() 读取 start_url中的URL, 并以 Parse 为回调函数生成Request 。
在回调函数内分析返回的(网页)内容,返回 Item 对象或者Request或者一个包括二者的可迭代容器。 返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的callback函数(函数可相同)。
在回调函数内,您可以使用选择器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 来分析网页内容,并根据分析的数据生成item。
最后,由spider返回的item将被存到数据库(由某些Item Pipeline处理)或使用Feed exports存入到文件中。
class DoubanSpiderSpider(scrapy.Spider):
#爬虫名 #与项目名不同
name = 'douban_spider'
#域名 #不在这个域名下不解析
allowed_domains = ['movie.douban.com']
#入口url,并将入口URL 扔进调度器【Schedule】中
start_urls = ['https://movie.douban.com/top250']
#扔进调度器【Schedule】之后,Schedule 告诉爬虫引擎自己准备好了,然后爬虫引擎让Downloader去下载数 据,获取页面
#然后将获取的页面返回值Spider文件中,让Spider进行解析,那如何解析文件就是下面的parse方法,这个 response就是Downloader的返回值,可以详细见上面的那张图
def parse(self, response):
print(response.text)
cmd >> scrapy crawl spider_name
可能遇见错误一:编码问题
import sys,io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')可能遇见错误二:不给解析
USER_AGENT = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Mobile Safari/537.36' #网站上自己看USER_AGENT
爬取第一类数据:纯数据
class DoubanSpiderSpider(scrapy.Spider):
#爬虫名 #与项目名不同
name = 'douban_spider'
#域名 #不在这个域名下不解析
allowed_domains = ['movie.douban.com']
#入口url,并将入口URL 扔进调度器【Schedule】中
start_urls = ['https://movie.douban.com/top250']
#扔进调度器【Schedule】之后,Schedule 告诉爬虫引擎自己准备好了,然后爬虫引擎让Downloader去下载数据, 获取页面
#然后将获取的页面返回值Spider文件中,让Spider进行解析,那如何解析文件就是下面的parse方法,这个response 就是Downloader
#的返回值,可以详细见上面的那张图
def parse(self, response):
movie_list=response.xpath("//div[@class='article']//ol[@class='grid_view']//li")
for i in movie_list:
Douban_item=DoubanItem() ##导入item包,你要存到item中
Douban_item['serial_number']=i.xpath(".//div[@class='item']//em/text()").extract_first() #获取第一个数据
#如果有多个数据,你想把数据拼接起来
#content=i.xpath(...).extract()
#for ii in content:
# c_s="".join(ii.split())
# =
print(Douban_item)
#将数据返回至pipe中,请仔细看scrapy的流程图就知道了,不加yield不行
yield Douban_item
爬取第二类数据:下页数据
next_link = response.xpath("//span[@class='next']/link/@href").extract()
if next_link:
next_link=next_link[0]
yield scrapy.Request("https://movie.douban.com/top250"+next_link,callback=self.parse)
4、存储内容
将爬取的数据导出json文件,csv文件
cmd >> scrapy crawl spider_name -o _name.json
cmd >> scrapy crawl spider_name -o _name.csv
保存文件至数据库
---settings.py--- # 先写数据库配置文件
MYSQL_HOST = 'localhost'
MYSQL_DBNAME = 'scrapy'
MYSQL_USER = 'root'
MYSQL_PASSWD = ''
MYSQL_PORT = 3306
---pipelines.py--- # 传入数据
import pymysql ##导入python中的mysql包,pymysql
from project.settings import MYSQL_HOST,MYSQL_DBNAME,MYSQL_USER,MYSQL_PASSWD,MYSQL_PORT
class DoubanPipeline(object):
def process_item(self, item, spider):
# open db
self.connect = pymysql.connect(
host=MYSQL_HOST,port=MYSQL_PORT,user=MYSQL_USER,db=MYSQL_DBNAME,
passwd=MYSQL_PASSWD,charset='utf8',use_unicode=True)
self.cursor = self.connect.cursor()
# insert db
num = item['serial_number']
sql = 'insert into test(num) values("%s")' % (num)
self.cursor.execute(sql)
self.connect.commit()
# close db
self.cursor.close()
self.connect.close()
return item
---settings.py--- #开启管道 ITEM_PIPELINES ,取消下面这个注释
ITEM_PIPELINES = {
'douban.pipelines.DoubanPipeline': 300,
}