python爬蟲學習筆記

第一步,創(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文件里設置USER-AGENT='瀏覽器實際user-agent'

得到返回的內(nèi)容response然后可以用xpath 或者css 對返回的response.body進行數(shù)據(jù)清洗提取

命令:response.xpath("http://title")

或者:

scrapy shell

進入scrapy環(huán)境

設置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

獲取原始數(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,關且內(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,要想打開文件后能夠顯示漢字,則需要設置輸出格式)

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文件的作用是將清洗后的數(shù)據(jù)存儲存在此文件中設置好的字段中并交給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文件中進行設置)

讓pipline.py文件生效的設置方法是,打開seting.py文件,找到“# Configure item pipelines”語句塊,把下面的“#ITEM_PIPELINES”語句塊解除注釋

第一種方法:open_spider 是spider.py打開運行的時候執(zhí)行

def open_spider(self,spider):

pass

第二種方法:close_spider 是spider.py 文件運行結束的時候執(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)容的時候需要設置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'))

使用丟棄模塊構建去重過濾器

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)設置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‘? ? #設置代理IP爬取數(shù)據(jù)

關于mysql數(shù)據(jù)據(jù)庫的sql語句執(zhí)行提交以及執(zhí)行結果獲取,影響的行等數(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)

獲取結果集中的第一條數(shù)據(jù):

rowData=cursor.fetchone()

獲取結果集中的第二條數(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)時間,那么請將此字段類型設置為:TIMESTAMP? 類型,并將其值設置為:CURRENT_TIMESTAMP, 這樣此字段在數(shù)據(jù)插入的時候會自動寫入當前日期時間

關于反爬蟲機制,請求時隨機更換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自帶的兩個模塊(兩個基礎包):

1.smtplib(負責發(fā)送郵件,即將構造好的郵件內(nèi)容發(fā)送出去)

2.email(負責構造發(fā)送內(nèi)容)

這兩個包無需安裝,可以直接import

smtp協(xié)議是TCP/IP 協(xié)議的一種(即簡單郵件傳輸協(xié)議),而python 的 smtplib 對smtp協(xié)議進行了封裝

smtplib(發(fā)送構造好的需要發(fā)送的email內(nèi)容的步驟)的具體使用方法如下:

server=smtplib.SMTP('smtp.163.com',25)#實例化smtp服務,并傳入smtp服務器地址和端口號

server.login('user','pass')#傳入在郵箱服務器地址設置好的用戶名和獲得的郵箱授權碼,登陸smtp服務器

server.sendmail('發(fā)件地址','收件地址’,msg.as_string())#其中msg.as_string()是將各種MIME(如:MIMEText,MIMEImage,MIMEMutipart)內(nèi)容轉換為字符串

server.quit()#退出郵件發(fā)送服務器

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具體使用三個參數(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構造base64數(shù)據(jù),用于發(fā)送郵件附件,具體構造方法如下:

fileContent=open(r'.\fujian.txt','rb').read() #以二進制模式讀取本地文件內(nèi)容,并將其賦給變量

txt=MIMEText(fileContent,'base64','utf-8')#將讀取到的文件內(nèi)容轉換為base64數(shù)據(jù)流,并將轉換的結果賦給txt變量

txt['Content-Type']='application/octet_stream']#設置數(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:郵件中包含附件文件,圖片,文本都可以添加,總之設置為mixed類型無論什么內(nèi)容均可發(fā)送

MIMEMutipart是代表郵件本身,MIMEText 和MIMEImage是代表郵件內(nèi)容,所以可以將MIMEText或者MIMEImage添加到MIMEMutipart中,如下 :

msg=MIMEMutipart(mixed)

msg.attach(MIMEText或者MIMEImage)

這樣就可以將構造好的圖片,文本,或者其它內(nèi)容一起發(fā)送出去

msg.as_string() 是將msg對象轉換為str類型

4.發(fā)送各種內(nèi)容的具體代碼實現(xiàn):

urllib的用法步驟:

1,引入urllib模塊

2.引入request模塊

3.引入parse模塊

import urllib

from urllib import reqeust

from urllib import parse

#構造新求參數(shù)

(1)請求頭

headers={'User-Agent':'mozila'}

(2)如果是post請求,構造請求數(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)

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容