持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情
Python专题的文章收录于专栏:Python专栏
1. 多协程(gevent库,queue模块)
利用多协程编程可以实现程序的异步运行,可以大大加快程序的运行速度
也就相当于在同一时间有多只爬虫在进行数据爬取
- 导入模块
from gevent import monkey
monkey.patch_all() #将程序编程协作式运行,实现异步
import gevent,requests
from gevent.queue import Queue
url_list = ['...','...','...',...] #将网站封装成列表
1. 不使用queue
- 首先需要定义一个执行爬虫任务的函数
def crawler(url):
r = requests,get(url)
print(url,r.status_code)
- 紧接着创建任务列表,然后利用
append方法逐个插入任务,插入的同时传入爬虫的函数及对应的地址,后续任务列表中的多个任务将会异步执行
tasks_list = [] #创建空的任务列表
for url in url_list:
task = gevent.spawn(crawler,url) #创建任务
tasks_list.append(task) #往任务列表添加任务
gevent.joinall(tasks_list) #执行列表中所有任务
注意上面的这个方法,实际上就是一个地址创建了一只爬虫,毋庸置疑造成了资源的浪费,所以效率并不高
2. 使用queue(效率更高)
- 首先创建一个队列,用于存放地址,便于后续爬虫读取要爬取数据的网址
work = Queue() #创建队列对象
for url in url_list:
work.put_nowait(url) #将网址放入队列中
- 然后定义爬取数据的函数,只要队列不为空,就从队头取出一个地址,并执行
request.get函数
def crawler():
while not work.empty(): #当队列不是空的时候,执行下面程序
url = work.get_nowait() #取出队列中的网址
r = requests.get(url)
print(url,work.qsize(),r.status_code) #qsize()用于判断队列中数量的多少
- 最后需要创建任务列表,这里一个任务代表着一个爬虫,在这里爬虫的数量可以自己选择,视地址数量而定,然后创建的爬虫合作先后从队列中取出地址,实现异步爬虫操作
tasks_list = []
for x in range(2): #相当于建立两个爬虫
task = gevent.spawn(crawler)
tasks_list.append(task)
gevent.joinall(tasks_list)
2. Scrapy(爬虫框架)
看来不管前端后端最终的道路都是框架
Scrapy(引擎):Scheduler(调度器)、Downloader(下载器)、Spiders(爬虫)、Item Pipeline(数据管道)
用法:
-
创建Scrapy项目
-
定义item(数据)
-
创建和编写spiders文件
-
修改setting.py文件
-
运行Scrapy爬虫
scrapy项目结构:
- 在终端创建Scrapy项目
d: #路径转至D盘
cd python #路径跳转至python文件(D:\python\)
scrapy startproject douban #在该目录中创建一个scrapy项目
- 定义你将要爬取的数据item,注意这里需要导入scrapy模块
利用Field()来创建不同的属性
import scrapy
class DoubanItem(scrapy.Item):
title = scrapy.Field() #定义书名的数据属性
publish = scrapy.Field() #定义出版信息的数据属性
score = scrapy.Field() #定义评分的数据属性
-
紧接着创建并编写spiders文件(这个文件是用于定义爬虫的,同时需要从上一步的items文件中引入创建的数据类)
-
这里定义一个爬虫类,然后在类里面定义
parse方法,该方法是默认处理response对象的方法
import scrapy,bs4
from ..items import DoubanItem
class DoubanSpider(scrapy.Spider):
name = 'douban' #定义爬虫的名字
allowed_domains = ['book.douban.com'] #定义爬虫网站的域名
start_urls = []
for i in range(3):
url = 'https://book.douban.com/top250?start='+str(i*25)
start_urls.append(url)
def parse(self,response): #parse是默认处理response对象的方法
bs = bs4.BeautifulSoup(response.text,'html.parser')
datas = bs.find_all('tr',class_="item")
for data in datas:
item = DoubanItem() #实例化DoubanItem这个类
item['title'] = data.find_all('a')[1]['title']
item['publish'] = data.find('p',class_='pl').text
item['score'] = data.find('span',class_='rating_nums').text
print(item['title']) #把获得的item传递给引擎
yield item
#real_url = "..."
#yield scrapy.Request(real_url,callback=self.parse_new)
#构造requests对象,需要再定义一个方法处理response
- 修改setting.py文件 在该文件里可以设置请求头、爬取速度等参数
#USER-AGENT='......' 修改请求头,将注释取消
ROBOTSTXT_OBEY = True #将True改为False,即不遵从robots协议
#DOWNLOAD_DELAY = 0 控制爬取速度
- 运行Scrapy爬虫(两种方式) 第一种(终端):
进入到当前框架所处目录下
执行scrapy crawl douban命令
d:
cd python
cd douban
scrapy crawl douban
第二种:
在最外层文件中新建一个main.py文件(即与scrapy.fcg同级)
然后用execute()输入运行scrapy的命令,以列表为参数
#在最外层文件新建一个main.py文件(与scrapy.fcg同级)
#main.py中代码如下:
from scrapy import cmdline #导入cmdline模块,控制终端命令行
cmdline.execute(['scrapy','crawl','douban'])
- 将爬取的数据进行存储 存储为csv文件:
#在setting.py中添加代码
FEED_URL = './storage/data/%(name)s.csv'
#FEED_URL是导出文件路径,将文件放至与main.py同级的storage文件夹中的data子文件夹里
FEED_FORMAT = 'csv'
#FEED_FORMAT是导出数据格式,得到csv格式
FEED_EXPORT_ENCODING = 'ansi'
#FEED_EXPORT_ENCODING是导出文件编码,ansi是一种在windows上的编码格式,也可变成'utf-8'用在mac电脑上
存储在excel文件:
首先需要在setting.py中取消ITEM_PIPLINES的注释
其次在piplines.py文件中写入以下代码:
#在piplines.py中:
import openpyxl
class JobuiPipline(object):
def __init__ (self):
self.wb = openpyxl.Workbook()
self.ws = self.wb.active
self.ws.append(['公司','职位',...])
def process_item(self,item,spider):
line = [item['...'],item['...'],...]
self.ws.append(line)
return item
def close_spider(self,spider):
self.wb.save('./jobui.xlsx')
self.wb.close()