新建爬虫项目
scrapy startproject 项目名称
创建爬虫文件
scrapy genspider 爬虫文件名称 要爬取的目标url的域(baidu.com)
运行爬虫
scrapy crawl 爬虫名称
以jobble为例:
-
- 创建项目:scrapy startproject jobbleproject
-
- 进入jobbleproject/jobbleproject/spider目录,新建爬虫文件:scrapy genspider jobble jobble.com
-
- 打开item文件:根据目标网站分析需要提取的数据,在item.py文件中添加需要获取的字段
class JobboleItem(scrapy.Item):
# define the fields for your item here like:
#标题
title = scrapy.Field()
#创建时间
create_date = scrapy.Field()
#文章地址
url = scrapy.Field()
#id
url_object_id = scrapy.Field()
#文章图片
front_image_url = scrapy.Field()
#文章图片地址
front_image_path = scrapy.Field()
# 点赞数
praise_nums = scrapy.Field()
#收藏数
bookmark_nums = scrapy.Field()
# 评论数
comment_nums = scrapy.Field()
#文章内容
content = scrapy.Field()
#标签
tags = scrapy.Field()
# 插入数据库语句
- 打开 jobboleproject/spider目录里的 jobbole.py,默认增加了下列代码:(也可以自行创建文件并添加以下代码)
class JobboleSpider(scrapy.Spider):
name = 'jobbole' # 爬虫名称
allowed_domains = ['jobbole.com'] # url的域
start_urls = ['http://blog.jobbole.com/all-posts/'] # 目标url(起始URL)
def parse(self, response):
pass
-
- 在parse方法中做数据的提取(可参考之前介绍的几种提取数据方法,以下介绍如何使用)
def parse(self, response):
# 获取url
response.url
# 使用item设置的字段
from jobbleproject.items import JobbleItems
#
# 使用xpath提取数据,scrapy提前封装好可以直接使用
response.xpath('xpath语法')
# css选择器
response.css('div.a div#q')
# 通过以上方法得到的是Selector类型,用以上方法转化成字符串
response.xpath('xpath语法').extact_first('如果没有提取到数据或数据为空可设置一个默认值') --> 获取一个并且是第一个
response.css('div.a div#q').extract() -->获取所有,返回一个列表
# 把获取到的数据交给管道做下载等任务
yield response.xpath('....')
# 发起一个请求
"""
url:设置请求的url地址
callback=None:设置请求的回调方法
method='GET'请求方式,默认为get请求
headers=None,设置请求头,字典类型
cookies=None,设置cookies信息,模拟用户登录,字典类型
meta=None:传递参数(字典类型)
encoding='utf-8':设置编码
dont_filter=False,是否要去重,默认为False,表示去重
errback=None,请求失败后的回调
"""
yield scrapy.Request(firstURL,callback=self.parse_tags_page)
-
- settings文件:设置请求头,UA,全局的请求头,激活管道、cookie、下载中间件,下载延时等等
# 是否遵守robot协议(默认为True表示遵守)
ROBOTSTXT_OBEY = False
# 是否携带cookie值,默认为遵守
COOKIES_ENABLED = False
# UA
DEFAULT_REQUEST_HEADERS = {
# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# 'Accept-Language': 'en',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0'
}
# 下载中间件
DOWNLOADER_MIDDLEWARES = {
'jobble.middlewares.ChufangDownloaderMiddleware': 543,
}
# 激活管道
ITEM_PIPELINES = {
'jobble.pipelines.ChufangPipeline': 300,
}
# mysql 数据库的信息
MYSQL_HOST = '127.0.0.1'
MYSQL_USER = 'root'
MYSQL_pwd = 'XXX'
MYSQL_DB = 'jobble'
MYSQL_PORT = 3306
MYSQL_CHARSET = 'utf8'
# 代理
PROXIES = [
{'ip_port': '61.128.208.94:3128','user_pwd': None},
{'ip_port': '61.128.208.94:3128','user_pwd': ‘XXX’}
]
# mongodb数据库配置信息
MONGO_HOST = '127.0.0.1'
MONGO_PORT = 27017
MONGO_DB = 'jobble'
-
- 管道piplines:
import scrapy
from jobbleproject.items import JobboleItem
class jobblezprojectPipeline(object):
def __init__(self):
"""
初始化方法
"""
self.client = pymysql.Connect(
'127.0.0.1','root','XXX','jobble',3306,charset='utf8'
)
self.cursor = self.client.cursor()
# self.mongo_client = pymongo.MongoClient(host='127.0.0.1',port=27017)
def open_spider(self,spider):
"""
爬虫启动的时候会调用一次
:param spider:
:return:
"""
print('爬虫开启')
def process_item(self, item, spider):
"""
做数据持久化
这个方法是必须实现的,爬虫文件中的所有ITEM
都会经过这个方法
:param item: 爬虫文件传递过来的item对象
:param spider: 爬虫文件实例化的对象
:return:
"""
# mysql数据库
sql,data = item.get_insert_sql_data(data_dict)
try:
# self.cursor.execute(sql,list(data_dict.values()))
self.cursor.execute(sql, data)
self.client.commit()
except Exception as err:
print(err)
self.client.rollback()
# 如果有多个管道文件,一定要注意return,item,
# 否则下一个管道无法接收到item
print('经过了管道')
return item
def close_spider(self,spider):
"""
爬虫结束的时候会调用一次
:param spider:
:return:
"""
self.client.close()
self.cursor.close()
print('爬虫结束')
mongo
class ChinazprojectPipeline(object):
def __init__(self,host,port,dbname):
# 创建连接
self.mongo_client = pymongo.MongoClient(host=host,port=port)
# 数据库
self.db = self.mongo_client[dbname]
@classmethod
def from_crawler(cls,crawler):
"""
MONGO_HOST = '127.0.0.1'
MONGO_PORT = 27017
MONGO_DB = 'jobble'
:param crawler:
:return:
"""
host = crawler.settings['MONGO_HOST']
port = crawler.settings['MONGO_PORT']
db = crawler.settings['MONGO_DB']
return cls(host,port,db)
def process_item(self,item,info):
"""
:param item:
:param info:
:return:
"""
# 往哪个集合插入
col_name = item.get_mongo_collectionName()
col = self.db[col_name]
dict_data = dict(item)
try:
col.insert(dict_data)
print('数据插入成功')
except Exception as err:
print('失败',err)
return item
def close_spider(self,spider):
"""
爬虫结束的时候会调用一次
:param spider:
:return:
"""
self.mongo_client.close()
print('爬虫结束')
-
- middleware:可设置下载中间件,作用:反爬虫
# 设置UA
class UserAgentDownloadMiddlerware(object):
def process_request(self, request, spider):
from fake_useragent import UserAgent
User_Agent = UserAgent()
random_ua = User_Agent.random
if random_ua:
# print('经过了下载中间件', random_ua)
request.headers['User-Agent'] = random_ua
#代理
class ProxiesDownloadMiddlerware(object):
def process_request(self, request, spider):
import random
import base64
proxies = spider.settings['PROXIES']
proxy = random.choice(proxies)
if proxy['user_pwd'] is None:
# 没有代理账户验证的代理使用方式
request.meta['proxy'] = proxy['ip_port']
else:
# 对账户密码进行base64编码
user_pwd = base64.b64encode(proxy['user_pwd'].encode('utf-8')).decode('utf-8')
# 对应到代理服务器的信令格式里
request.headers['Proxy-Authorization'] = 'Basic ' + user_pwd
request.meta['proxy'] = proxy['ip_port']