第一步塞赂,創(chuàng)建 scrapy 工程:
命令:scrapy startproject? mySpiderLearn
第二步,進入工程目錄
命令:cd mySpiderLearn
第三步:創(chuàng)建爬蟲(scrapy 自帶四種爬蟲模板分別是:basic ,crawl, csvfeed, xmlfeed)
命令:scrapy genspider --template=basic superspider sy.hr1000.com
第四步:練習在命令行中用shell來直接訪問網(wǎng)站獲取返回數(shù)據(jù)
命令: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文件里設(shè)置USER-AGENT='瀏覽器實際user-agent'
得到返回的內(nèi)容response然后可以用xpath 或者css 對返回的response.body進行數(shù)據(jù)清洗提取
命令:response.xpath("http://title")
或者:
scrapy shell
進入scrapy環(huán)境
設(shè)置URL
url='http://www.baidu.com/'
設(shè)置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
獲取原始數(shù)據(jù)
req=Request(url,headers=headers)
r=fetch(req)
用xpath清洗數(shù)據(jù)
rsponse.xpath("http://title").extract()
#response.xpath 提取頁面內(nèi)容的幾種方式
1.根據(jù)元素的類名來提取
response.xpath("http://div[@class='hd']//span/text()").extract()
2.根據(jù)類名 + 內(nèi)容來提取,例如下面的例子是提取span標簽類名為rating_num,關(guān)且內(nèi)容大于9.2的所有內(nèi)容提取出來
response.xpath("http://span[@class='rating_num'? and text()>9.2)/text()").extract()
3.根據(jù)類名的開頭字母來提取,例如下面的例子提取所有的span標簽中類名以t開頭的所有元素的內(nèi)容
response.xpath("http://span[starts-with(@class,'t')]/text()").extract()
#response.css 提取頁面內(nèi)容的幾種方式
1.根據(jù)標簽名稱提取某一類標簽元素的內(nèi)容
response.css('span::text').extract()
2.根據(jù)標簽的子節(jié)點提取元素的內(nèi)容,例如下面的例子是提取所有div標簽下面的a標簽下面的類名稱為title的第一個span標簽的內(nèi)容
response.css('div>a>span[class=title]:nth-of-type(1)::text').extract()
3.例如下面的例子是取所有類名稱為hd的標簽下面的所有a標簽下面的所以類名稱為title的第一個span 標簽的內(nèi)容
response.css("div>a>span[class='title']:nth-of-type(1)::text").extract()
4.例如下面的例子是取所有a標簽的href屬性值
response.css("a::attr(href)").extract()
將提取內(nèi)容直接輸出到本地文件如:(csv文件,json文件契邀,xml文件......)
1.輸出為csv文件,在命令行輸入:
scrapy crawl spider2 -t csv -o douban.csv
2.輸出為json文件摆寄,在命令行中輸入:(注意輸出為json文件的時候默認保存的編碼為UNICODE,要想打開文件后能夠顯示漢字,則需要設(shè)置輸出格式)
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相關(guān)設(shè)置:
1.FEED_URL :存儲路徑
2.FEED_FORMAT:存儲格式
3.FEED_EXPORT_ENCODING:編碼格式
4.FEED_EXPORT_FIELDS:存儲字段
items.py文件的作用是將清洗后的數(shù)據(jù)存儲存在此文件中設(shè)置好的字段中并交給pipelines.py文件處理
items.py文件中的類名稱取決于spidder.py文件中的from ..items import itemsClassName(items中的類名)
items.py文件中可以有多個類微饥,均可以在spidder.py中用from 語句引入
pipline.py文件用于處理spider.py文件獲取的數(shù)據(jù)逗扒,此文件中主要有三種方法:(注意如果想要pipelines文件生效必須要在seting.py文件中進行設(shè)置)
讓pipline.py文件生效的設(shè)置方法是,打開seting.py文件欠橘,找到“# Configure item pipelines”語句塊矩肩,把下面的“#ITEM_PIPELINES”語句塊解除注釋
第一種方法:open_spider 是spider.py打開運行的時候執(zhí)行
def open_spider(self,spider):
pass
第二種方法:close_spider 是spider.py 文件運行結(jié)束的時候執(zhí)行
def? close_spider(self,spider):
pass
第三個方法:process_item 是處理spider.py文件返回的數(shù)據(jù)
def process_item(self,item,spider):
pass
在pipline.py文件中把數(shù)據(jù)寫入json文件的時候,需要引入json? 庫肃续,在dumps json內(nèi)容的時候需要設(shè)置ensure_ascii=false 如下:
import json
items=json.dumps(dict(item),ensure_ascii=False)
不需要實例化調(diào)用類(在類中的方法調(diào)用類,方法的第一個參數(shù)必須是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'))
使用丟棄模塊構(gòu)建去重過濾器
1.引入丟棄模塊
from scrapy.exceptions import DropItem
在命令行中創(chuàng)建mysql數(shù)據(jù)庫的過程:
1.進入mysql上下文狀態(tài)
命令行中輸入:mysql -u root -p liangwei@
2.查看數(shù)據(jù)庫信息
命令行中輸入:show databases;
3.創(chuàng)建數(shù)據(jù)庫
create database databaseName;
4. 進入創(chuàng)建的數(shù)據(jù)庫的上下文:databaseName=數(shù)據(jù)庫名稱
use databaseName;
5.在當前數(shù)據(jù)庫上下文創(chuàng)建數(shù)據(jù)表dataName=數(shù)據(jù)庫名稱:
命令行中輸入:create table dataName(filed1 char(128),filed2 char(128))
4.查看當前數(shù)據(jù)表:
在命令行中輸入:show tables;
6.查看表的字段及描述信息黍檩,databaseName=數(shù)據(jù)庫名稱
在命令行中輸入:describe (databaseName);
連接mysql報錯(pymysql.err.OperationalError: (1045, "Access denied for user 'root'@'localhost' (using password: YES)"))
命令行中執(zhí)行:ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'liangwei939@'
如果仍然報錯,就新建一個用戶始锚,用新用戶連接mysql
sql語句字符串格式化處理方法:
例子:sql="insert into 表名(字段一,字段二) values('%s','%s')"%(a,b)
有時候采集的數(shù)據(jù)中有太多的單引號和雙引號刽酱,以致于影mysql數(shù)據(jù)庫插入數(shù)據(jù),要替換掉這些雙引號瞧捌,單引號棵里,最好的辦法是利用正則表達式,如下:
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()
出現(xiàn)? 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('自定義函數(shù)1',自定義函數(shù)2',str.split,.....)
out_processor=Join()
兩個Filed()參數(shù),對其獲取的item數(shù)據(jù)進行處理清洗
如:
def process1(a):
return a.split('/')
riQi=Field(input_processor=MapCompose(process1,str.split),output_processor=Join())
在scrapy 中動態(tài)設(shè)置User-Agent的方法
首先安裝庫:pip install fake_useragent
安裝成功之后:
第一步皮钠,在middlewares.py 文件中引入:
from fake_useragent import FakeUserAgent
第二步,在middlewares.py文件中新創(chuàng)建一個類如:
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‘? ? #設(shè)置代理IP爬取數(shù)據(jù)
關(guān)于mysql數(shù)據(jù)據(jù)庫的sql語句執(zhí)行提交以及執(zhí)行結(jié)果獲取赠法,影響的行等數(shù)據(jù)的獲取:
例如:
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公司名稱'"
執(zhí)行此sql語句并且獲取執(zhí)行后影響的數(shù)據(jù)行數(shù)用:
rs=cursor.execut(sql)
獲取結(jié)果集中的第一條數(shù)據(jù):
rowData=cursor.fetchone()
獲取結(jié)果集中的第二條數(shù)據(jù):
rowData=cursor.fetchone()
插入一條數(shù)據(jù)并獲取執(zhí)行后影響的數(shù)據(jù)行數(shù):
sql="insert into syhr1000(companyName,companyAddress)values('XXXX','XXXX')"
rs=cursor.execute(sql)
如果想要在插入數(shù)據(jù)的時候麦轰,給一個字段默認寫入當前的系統(tǒng)時間,那么請將此字段類型設(shè)置為:TIMESTAMP? 類型砖织,并將其值設(shè)置為:CURRENT_TIMESTAMP款侵, 這樣此字段在數(shù)據(jù)插入的時候會自動寫入當前日期時間
關(guān)于反爬蟲機制,請求時隨機更換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 發(fā)郵件用到python自帶的兩個模塊(兩個基礎(chǔ)包):
1.smtplib(負責發(fā)送郵件,即將構(gòu)造好的郵件內(nèi)容發(fā)送出去)
2.email(負責構(gòu)造發(fā)送內(nèi)容)
這兩個包無需安裝娜氏,可以直接import
smtp協(xié)議是TCP/IP 協(xié)議的一種(即簡單郵件傳輸協(xié)議)拳缠,而python 的 smtplib 對smtp協(xié)議進行了封裝
smtplib(發(fā)送構(gòu)造好的需要發(fā)送的email內(nèi)容的步驟)的具體使用方法如下:
server=smtplib.SMTP('smtp.163.com',25)#實例化smtp服務(wù),并傳入smtp服務(wù)器地址和端口號
server.login('user','pass')#傳入在郵箱服務(wù)器地址設(shè)置好的用戶名和獲得的郵箱授權(quán)碼贸弥,登陸smtp服務(wù)器
server.sendmail('發(fā)件地址','收件地址’,msg.as_string())#其中msg.as_string()是將各種MIME(如:MIMEText,MIMEImage,MIMEMutipart)內(nèi)容轉(zhuǎn)換為字符串
server.quit()#退出郵件發(fā)送服務(wù)器
email模塊的使用首先是要導(dǎo)入相關(guān)的email模塊下的MIME類型窟坐,比如常用的MIME類型有:
MIMEText(文本類型)
MIMEImage(圖片類型)
MIMEMutipart(混合類型:圖片,文本,聲音哲鸳,視頻.......)
具體的導(dǎo)入方式如下:
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.mutipart import MIMEMutipart
具體的使用方式如下:
1.MIMEText具體使用三個參數(shù)臣疑,這三個參數(shù)分別為:
(1)要發(fā)送的文本內(nèi)容
(2)文本內(nèi)容格式(一般為:text/plain 和 text/html 兩種中的一種,說白了就是文本和html)
(3)文本編碼(常用的是'utf-8')
MIMEText使用示例如下:
url='http://www.xyeds.cn/'
textContent='<a href="%s">這是一個html郵件內(nèi)容</a>'%url
htmlsub=MIMEText(textContent,'html','utf-8)
#如果不加下面這行代碼會把超文本html內(nèi)容當成文本形式顯示
htmlsub["Content-Disposition"]='attachment;filename="csdn.html"'
2.MIMEText構(gòu)造base64數(shù)據(jù)徙菠,用于發(fā)送郵件附件讯沈,具體構(gòu)造方法如下:
fileContent=open(r'.\fujian.txt','rb').read() #以二進制模式讀取本地文件內(nèi)容,并將其賦給變量
txt=MIMEText(fileContent,'base64','utf-8')#將讀取到的文件內(nèi)容轉(zhuǎn)換為base64數(shù)據(jù)流懒豹,并將轉(zhuǎn)換的結(jié)果賦給txt變量
txt['Content-Type']='application/octet_stream']#設(shè)置數(shù)據(jù)流內(nèi)容傳輸方式
txt.add_header('Content-Disposition','attachment',filename='fujian.txt')#添加頭信息內(nèi)容處理方式為附件芙盘,并將其重命名
綜上所述MIMEText有兩種實現(xiàn)方式,一種是實現(xiàn)文本類型的郵件內(nèi)容脸秽,另一種是實現(xiàn)郵件附件
2.MIMEImage對象只需要將讀取到的圖片內(nèi)容傳入即可儒老,具體使用方法如下:
image_file=open(r'./my.jpg','rb').read()#讀入圖片二進制內(nèi)容
image=MIMEImage(image_file)#對圖片內(nèi)容進行MIMEIma編碼
image.add_header['Content_ID','<image1>']#添加圖片頭信息
#將讀入的圖片重新命名
image['Content-Disposition']='attachment;filename="myfilename.jpg"'
3.MIMEMutipart對象創(chuàng)建的內(nèi)容主要有以下三種類型:
(1),mutipart/alternative :郵件正文中只能包含純文本和html文本內(nèi)容
(2),mutipart/related:郵件正文中可以包含圖片,聲音记餐,視頻等內(nèi)嵌資源內(nèi)容
(3),mutipart/mixed:郵件中包含附件文件驮樊,圖片,文本都可以添加片酝,總之設(shè)置為mixed類型無論什么內(nèi)容均可發(fā)送
MIMEMutipart是代表郵件本身囚衔,MIMEText 和MIMEImage是代表郵件內(nèi)容,所以可以將MIMEText或者MIMEImage添加到MIMEMutipart中雕沿,如下 :
msg=MIMEMutipart(mixed)
msg.attach(MIMEText或者MIMEImage)
這樣就可以將構(gòu)造好的圖片练湿,文本,或者其它內(nèi)容一起發(fā)送出去
msg.as_string() 是將msg對象轉(zhuǎn)換為str類型
4.發(fā)送各種內(nèi)容的具體代碼實現(xiàn):
urllib的用法步驟:
1,引入urllib模塊
2.引入request模塊
3.引入parse模塊
import urllib
from urllib import reqeust
from urllib import parse
#構(gòu)造新求參數(shù)
(1)請求頭
headers={'User-Agent':'mozila'}
(2)如果是post請求审轮,構(gòu)造請求數(shù)據(jù)
data={'user':'lw','pass':'password'}
將post數(shù)據(jù)解析成字符串然后字節(jié)化
data=bytes(parse.urlencode(data),encoding='utf-8')
(3)建立請求對象
request=request.Request(url=url,data=data,headers=headers,method='POST')
(4)發(fā)送請求獲取返回數(shù)據(jù)
response=request.urlopen(request)