第一步,创建 scrapy 工程:
命令:scrapy startproject mySpiderLearn
第二步,进入工程目录
命令:cd mySpiderLearn
第三步:创建爬虫(scrapy 自带四种爬虫模板分别是:basic ,crawl, csvfeed, xmlfeed)
命令:scrapy genspider --template=basic superspider sy.hr1000.com
第四步:练习在命令行中用shell来直接访问网站获取返回数据
命令:scrapy shell -s User_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36" http://www.baidu.com/
遇到访问被拒绝,status_code=403的情况,请在settings.py文件里设置USER-AGENT='浏览器实际user-agent'
得到返回的内容response然后可以用xpath 或者css 对返回的response.body进行数据清洗提取
命令:response.xpath("//title")
或者:
scrapy shell
进入scrapy环境
设置URL
url='http://www.baidu.com/'
设置headers
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}
引入Request
from scrapy import Request
获取原始数据
req=Request(url,headers=headers)
r=fetch(req)
用xpath清洗数据
rsponse.xpath("//title").extract()
#response.xpath 提取页面内容的几种方式
1.根据元素的类名来提取
response.xpath("//div[@class='hd']//span/text()").extract()
2.根据类名 + 内容来提取,例如下面的例子是提取span标签类名为rating_num,关且内容大于9.2的所有内容提取出来
response.xpath("//span[@class='rating_num' and text()>9.2)/text()").extract()
3.根据类名的开头字母来提取,例如下面的例子提取所有的span标签中类名以t开头的所有元素的内容
response.xpath("//span[starts-with(@class,'t')]/text()").extract()
#response.css 提取页面内容的几种方式
1.根据标签名称提取某一类标签元素的内容
response.css('span::text').extract()
2.根据标签的子节点提取元素的内容,例如下面的例子是提取所有div标签下面的a标签下面的类名称为title的第一个span标签的内容
response.css('div>a>span[class=title]:nth-of-type(1)::text').extract()
3.例如下面的例子是取所有类名称为hd的标签下面的所有a标签下面的所以类名称为title的第一个span 标签的内容
response.css("div>a>span[class='title']:nth-of-type(1)::text").extract()
4.例如下面的例子是取所有a标签的href属性值
response.css("a::attr(href)").extract()
将提取内容直接输出到本地文件如:(csv文件,json文件,xml文件......)
1.输出为csv文件,在命令行输入:
scrapy crawl spider2 -t csv -o douban.csv
2.输出为json文件,在命令行中输入:(注意输出为json文件的时候默认保存的编码为UNICODE,要想打开文件后能够显示汉字,则需要设置输出格式)
scrapy crawl spider2 -t json -o douban.json -s FEED_EXPORT_ENCODING='utf-8'
3.输出为xml文件,在命令行输入:
scrapy crawl spider2 -t xml -o douban.xml
Feed exports相关设置:
1.FEED_URL :存储路径
2.FEED_FORMAT:存储格式
3.FEED_EXPORT_ENCODING:编码格式
4.FEED_EXPORT_FIELDS:存储字段
items.py文件的作用是将清洗后的数据存储存在此文件中设置好的字段中并交给pipelines.py文件处理
items.py文件中的类名称取决于spidder.py文件中的from ..items import itemsClassName(items中的类名)
items.py文件中可以有多个类,均可以在spidder.py中用from 语句引入
pipline.py文件用于处理spider.py文件获取的数据,此文件中主要有三种方法:(注意如果想要pipelines文件生效必须要在seting.py文件中进行设置)
让pipline.py文件生效的设置方法是,打开seting.py文件,找到“# Configure item pipelines”语句块,把下面的“#ITEM_PIPELINES”语句块解除注释
第一种方法:open_spider 是spider.py打开运行的时候执行
def open_spider(self,spider):
pass
第二种方法:close_spider 是spider.py 文件运行结束的时候执行
def close_spider(self,spider):
pass
第三个方法:process_item 是处理spider.py文件返回的数据
def process_item(self,item,spider):
pass
在pipline.py文件中把数据写入json文件的时候,需要引入json 库,在dumps json内容的时候需要设置ensure_ascii=false 如下:
import json
items=json.dumps(dict(item),ensure_ascii=False)
不需要实例化调用类(在类中的方法调用类,方法的第一个参数必须是cls)如下:
class MyspiderlearnPipelineToJson(object):
def __init__(self,fpath):
self.fpath=fpath
@classmethod
def from_crawler(cls,crawler):
cls(fpath=crawler.settings.get('SAVE_FILE_PATH'))
使用丢弃模块构建去重过滤器
1.引入丢弃模块
from scrapy.exceptions import DropItem
在命令行中创建mysql数据库的过程:
1.进入mysql上下文状态
命令行中输入:mysql -u root -p liangwei@
2.查看数据库信息
命令行中输入:show databases;
3.创建数据库
create database databaseName;
4. 进入创建的数据库的上下文:databaseName=数据库名称
use databaseName;
5.在当前数据库上下文创建数据表dataName=数据库名称:
命令行中输入:create table dataName(filed1 char(128),filed2 char(128))
4.查看当前数据表:
在命令行中输入:show tables;
6.查看表的字段及描述信息,databaseName=数据库名称
在命令行中输入:describe (databaseName);
连接mysql报错(pymysql.err.OperationalError: (1045, "Access denied for user 'root'@'localhost' (using password: YES)"))
命令行中执行:ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'liangwei939@'
如果仍然报错,就新建一个用户,用新用户连接mysql
sql语句字符串格式化处理方法:
例子:sql="insert into 表名(字段一,字段二) values('%s','%s')"%(a,b)
有时候采集的数据中有太多的单引号和双引号,以致于影mysql数据库插入数据,要替换掉这些双引号,单引号,最好的办法是利用正则表达式,如下:
re.sub("[\",\']","",oldStr)
正则表达式中的re.S表示跨行匹配
例:
a='adfsf,
fdslfjl,
fd7dfsio,'
re.search('(f)',a,re.S) 匹配三行中的所有f
在spider文件中引入:
from scrapy .Loader import ItemLoader
作用是利用
ItemLoader.add_xpath('field',xpath_Express)
ItemLoader.add_css('field',css_Express)
ItemLoader.add_value('field',变量)
最后返回item.loder_item()字段值:
return ItemLoader.load_item()
出现 itemsL.add_xpath('riQi',r'//span[@property="v:initialReleaseDate"]/text()') 此错误的原因首先考虑 ItemLoader.add_xpath=('field',xpath_Express) 中间是否是加了等号,因为加了等号之后代码不报错,运行时报错
在items.py文件中引入:
from scrapy.loader.processors import Compose,MapCompose,Join
作用是利用
input_processor=MapCompose('自定义函数1',自定义函数2',str.split,.....)
out_processor=Join()
两个Filed()参数,对其获取的item数据进行处理清洗
如:
def process1(a):
return a.split('/')
riQi=Field(input_processor=MapCompose(process1,str.split),output_processor=Join())
在scrapy 中动态设置User-Agent的方法
首先安装库:pip install fake_useragent
安装成功之后:
第一步,在middlewares.py 文件中引入:
from fake_useragent import FakeUserAgent
第二步,在middlewares.py文件中新创建一个类如:
class DwMiddleWare(object):
def __init__(self):
self.ua=FakeUserAgent()
def process_request(self,request,spider):
request['headers']=self.ua.random
request.meta['proxy']='http://ip地址:80‘ #设置代理IP爬取数据
关于mysql数据据库的sql语句执行提交以及执行结果获取,影响的行等数据的获取:
例如:
mysqlconn=pymysql.connect(host='localhost',user='learn',password='liangwei',port=3306,dbtable='spider2',charset='utf8')
cursor=mysqlconn.cursor()
sql="select * from xyhr1000 where companyName='XXX公司名称'"
执行此sql语句并且获取执行后影响的数据行数用:
rs=cursor.execut(sql)
获取结果集中的第一条数据:
rowData=cursor.fetchone()
获取结果集中的第二条数据:
rowData=cursor.fetchone()
插入一条数据并获取执行后影响的数据行数:
sql="insert into syhr1000(companyName,companyAddress)values('XXXX','XXXX')"
rs=cursor.execute(sql)
如果想要在插入数据的时候,给一个字段默认写入当前的系统时间,那么请将此字段类型设置为:TIMESTAMP 类型,并将其值设置为:CURRENT_TIMESTAMP, 这样此字段在数据插入的时候会自动写入当前日期时间
关于反爬虫机制,请求时随机更换User_Agent的方法:
pip install fake_useragent
1.打开 middlewares.py文件,并引入FakeUserAgent方法如下:
from fake_useragent import FakeUserAgent
2.新建立一个类,并且将此类的类名更新到settings.py文件中的DOWNLOADER_MIDDLEWARES项下面,如:
class camouflageUserAgent(object):
'syHr1000Com.middlewares.camouflageUserAgent':543,
3.在这个新建立的类中初始化FakeUserAgent 例如:
def __init__(self):
self.ua=FakeUserAgent()
4.在这个新建立的类中新建立一个方法,名称为process_request(self,request,spider):例如:
def process_request(self,request,spider):
request.headers['User_Agent']=self.ua.random
至此,请求页面时随机更换User_Agent的整个步骤完成
更换访问IP的方法,在上面第四步 def process_request(self,request,spider):中改变proxy属性,例如:
def process_request(self,request,spider):
request.meta['proxy']='http://代理ip地址:端口'
python 发邮件用到python自带的两个模块(两个基础包):
1.smtplib(负责发送邮件,即将构造好的邮件内容发送出去)
2.email(负责构造发送内容)
这两个包无需安装,可以直接import
smtp协议是TCP/IP 协议的一种(即简单邮件传输协议),而python 的 smtplib 对smtp协议进行了封装
smtplib(发送构造好的需要发送的email内容的步骤)的具体使用方法如下:
server=smtplib.SMTP('smtp.163.com',25)#实例化smtp服务,并传入smtp服务器地址和端口号
server.login('user','pass')#传入在邮箱服务器地址设置好的用户名和获得的邮箱授权码,登陆smtp服务器
server.sendmail('发件地址','收件地址’,msg.as_string())#其中msg.as_string()是将各种MIME(如:MIMEText,MIMEImage,MIMEMutipart)内容转换为字符串
server.quit()#退出邮件发送服务器
email模块的使用首先是要导入相关的email模块下的MIME类型,比如常用的MIME类型有:
MIMEText(文本类型)
MIMEImage(图片类型)
MIMEMutipart(混合类型:图片,文本,声音,视频.......)
具体的导入方式如下:
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.mutipart import MIMEMutipart
具体的使用方式如下:
1.MIMEText具体使用三个参数,这三个参数分别为:
(1)要发送的文本内容
(2)文本内容格式(一般为:text/plain 和 text/html 两种中的一种,说白了就是文本和html)
(3)文本编码(常用的是'utf-8')
MIMEText使用示例如下:
url='http://www.xyeds.cn/'
textContent='<a href="%s">这是一个html邮件内容</a>'%url
htmlsub=MIMEText(textContent,'html','utf-8)
#如果不加下面这行代码会把超文本html内容当成文本形式显示
htmlsub["Content-Disposition"]='attachment;filename="csdn.html"'
2.MIMEText构造base64数据,用于发送邮件附件,具体构造方法如下:
fileContent=open(r'.\fujian.txt','rb').read() #以二进制模式读取本地文件内容,并将其赋给变量
txt=MIMEText(fileContent,'base64','utf-8')#将读取到的文件内容转换为base64数据流,并将转换的结果赋给txt变量
txt['Content-Type']='application/octet_stream']#设置数据流内容传输方式
txt.add_header('Content-Disposition','attachment',filename='fujian.txt')#添加头信息内容处理方式为附件,并将其重命名
综上所述MIMEText有两种实现方式,一种是实现文本类型的邮件内容,另一种是实现邮件附件
2.MIMEImage对象只需要将读取到的图片内容传入即可,具体使用方法如下:
image_file=open(r'./my.jpg','rb').read()#读入图片二进制内容
image=MIMEImage(image_file)#对图片内容进行MIMEIma编码
image.add_header['Content_ID','<image1>']#添加图片头信息
#将读入的图片重新命名
image['Content-Disposition']='attachment;filename="myfilename.jpg"'
3.MIMEMutipart对象创建的内容主要有以下三种类型:
(1),mutipart/alternative :邮件正文中只能包含纯文本和html文本内容
(2),mutipart/related:邮件正文中可以包含图片,声音,视频等内嵌资源内容
(3),mutipart/mixed:邮件中包含附件文件,图片,文本都可以添加,总之设置为mixed类型无论什么内容均可发送
MIMEMutipart是代表邮件本身,MIMEText 和MIMEImage是代表邮件内容,所以可以将MIMEText或者MIMEImage添加到MIMEMutipart中,如下 :
msg=MIMEMutipart(mixed)
msg.attach(MIMEText或者MIMEImage)
这样就可以将构造好的图片,文本,或者其它内容一起发送出去
msg.as_string() 是将msg对象转换为str类型
4.发送各种内容的具体代码实现:
urllib的用法步骤:
1,引入urllib模块
2.引入request模块
3.引入parse模块
import urllib
from urllib import reqeust
from urllib import parse
#构造新求参数
(1)请求头
headers={'User-Agent':'mozila'}
(2)如果是post请求,构造请求数据
data={'user':'lw','pass':'password'}
将post数据解析成字符串然后字节化
data=bytes(parse.urlencode(data),encoding='utf-8')
(3)建立请求对象
request=request.Request(url=url,data=data,headers=headers,method='POST')
(4)发送请求获取返回数据
response=request.urlopen(request)