1. 程式人生 > >phoenix_main的web之路的歷程

phoenix_main的web之路的歷程

之前一直在做web開發,最近根據公司需要再次搞起了爬蟲,雖然之前搞過,可是許多東西都忘得東東西西,敲起鍵盤來也是特別費勁,影響開發效率。今天週末,So特來整理一下。其實我不太喜歡寫部落格的,可是不寫的話,又有不太好的地方,不是記不住什麼,而是許多公司看重這個,雖然我覺得技術牛的永遠是技術牛的,小白也會慢慢的成長。同時作為一個程式設計師,總要為這個社會發點實用的乾貨,方便我們一起共同成長,畢竟閉門造車的生活很難熬,希望今後的日子裡,我願在技術大牛的路上與大家共同前行,有什麼做的不好的地方,希望大家多多指教。下面進入爬蟲正題:

1.urllib方法

1、常用方法
    1、urllib.request.urlopen("網址")
      1、作用 :向網站發起一個請求並獲取響應
        位元組流 = response.read()
        字串 = response.read().decode("utf-8")
        encode() : 字串 --> bytes
        decode() : bytes  --> 字串
      2、重構User-Agent
        1、不支援重構User-Agent :urlopen()
        2、支援重構User-Agent
          urllib.request.Request(新增User-Agent)
    2、urllib.request.Request("網址",headers="字典")
      User-Agent是爬蟲和反爬蟲鬥爭的第一步,傳送請求必須帶User-Agent
      1、使用流程(見 02_urllib.request.Request.py)
        1、利用Request()方法構建請求物件
	    2、利用urlopen()方法獲取響應物件
	    3、利用響應物件的read().decode("utf-8")獲取內容
#02_urllib.request.Request.py
import urllib.request

url = "http://www.baidu.com/"
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"}
# 1.建立請求物件(有User-Agent)
req = urllib.request.Request(url,headers=headers)
# 2.獲取響應物件(urlopen())
res = urllib.request.urlopen(req)
# 3.響應物件read().decode("utf-8")
#html = res.read().decode("utf-8")
#print(html)
print(res.getcode())
print(res.geturl())

      2、響應物件response的方法
        1、read() :讀取伺服器響應的內容
	    2、getcode()
	     1、作用
	    	 返回HTTP的響應碼
	      	 print(respones.getcode())
	      	 200 :成功
	     	 4XX :伺服器頁面出錯
	    	 5XX :伺服器出錯
       3、geturl()
	    	1、作用 :返回實際資料的URL(防止重定向問題)
2、urllib.parse模組
    1、urlencode(字典)  ## 注意:引數一定要為字典
       urlencode({"wd":"美女"})
       wd=%e8.......
       du = {"wd":"江西唯康資訊網路有限公司"}

     2、quote(字串) 
      	key = urllib.parse.quote("字串")
      	baseurl = "http://www.baidu.com/s?wd="
      	key = input("請輸入要搜尋的內容:")
      	#進行quote()編碼
      	key = urllib.parse.quote(key)
     	url = baseurl + key
      	print(url)
#例:
import urllib.request
import urllib.parse

#拼接URL
baseurl = "http://www.baidu.com/s?"
key = input("請輸入要搜尋的內容:")
#進行urlencode()編碼
wd = {"wd":key}
key = urllib.parse.urlencode(wd)

url = baseurl + key
headers = {"User-Agent":"Mozilla/5.0"}
# 建立請求物件
req = urllib.request.Request(url,headers=headers)
# 獲取響應物件
res = urllib.request.urlopen(req)
html = res.read().decode("utf-8")

#寫入本地檔案
with open("搜尋.html","w",encoding="gb18030") as f:
    f.write(html)
3、請求方式及例項
  1、GET
    1、特點 :查詢引數在URL地址中顯示
    2、案例 :抓取百度貼吧
  2、POST(在Request方法中新增data引數)
    1、urllib.request.Request(url,data=data,headers=headers)
    data :表單資料以bytes型別提交,不能是str
    2、處理表單資料為bytes型別
      1、把Form表單資料定義為字典data
      2、urlencode(data)
      3、轉為bytes資料型別 :bytes()
    3、有道翻譯案例
    4、有道翻譯返回的是json格式的字串,如何把json格式的字串轉換為Python中字典
      import json
      r_dict = json.loads(r_json)

2.re表示式

 正則表示式re
    1、使用流程
      1、建立編譯物件 :p = re.compile("正則表示式")
      2、對字串匹配 :r = p.match("字串")
      3、獲取匹配結果 :print(r.group())
    2、常用方法
      1、match(s) :字串開頭的第1個,返回物件
      2、search(s):從開始往後找,匹配第1個,返回物件
      3、group()  :從match或search返回物件中取值
      4、findall():所有全部匹配,返回一個列表
    3、表示式
      .  匹配任意字元(不能匹配\n)
      \d 數字
      \s 空白字元
      \S 非空白字元  
      [...] 包含[]內容 :A[BCD]E  --> ABE  ACE  ADE 
      \w 字母、數字、_

      *  0次或多次
      ?  0次或1次
      +  1次或多次
      {m} m次
      {m,n} m-n次  AB{1,3}C --> ABC ABBC ABBBC

      貪婪匹配(.*) :在整個表示式匹配成功的前提下,儘可能多的匹配*

      非貪婪匹配(.*?) :在整個表示式匹配成功的前提下,儘可能少的匹配*
    4、示例(貪婪模式和非貪婪模式)
      見 :見貪婪匹配和非貪婪匹配示例.py
#貪婪匹配和非貪婪匹配示例.py
import re

s = """<div><p>仰天大笑出門去,我輩豈是蓬蒿人</div></p>
<div><p>床前明月光,疑是地上霜</div></p>"""
# 建立編譯物件
# re.S作用 :使 . 能夠匹配 \n 在內的所有字元
# 貪婪匹配 : .*  
p = re.compile('<div><p>.*</div></p>',re.S)
#非貪婪匹配 : .*?
p = re.compile('<div><p>.*?</div></p>',re.S)
# 匹配字串s
r = p.findall(s)
print(r)
    5、findall()的分組
    #例:
	import re
	#解釋 :先按照整體匹配出來,然後再匹配()中的
	# 如果有2個或者多個(),則以元組的方式取顯示

	s = "A B C D"
	p1 = re.compile('\w+\s+\w+')
	print(p1.findall(s))
	# ['A B','C D']

	p2 = re.compile('(\w+)\s+\w+')
	# 第1步 :['A B','C D']
	# 第2步 :['A','C']
	print(p2.findall(s))

	p3 = re.compile('(\w+)\s+(\w+)')
	# 第1步 :['A B','C D']
	# 第2步 :[('A','B'),('C','D')]
	print(p3.findall(s))

3.requests方法

  1、安裝(用管理員身份去開啟Anaconda Prompt)
    Anaconda   : conda install requests
    Windows cmd: python -m pip install requests
      ## 以管理員身份去執行pip安裝命令
  2、常用方法
    1、get(url,headers=headers) : 發起請求,獲取響應物件
    2、response屬性
      1、response.text :返回字串型別
      2、response.content : 返回bytes型別
        1、應用場景 :爬取非結構化資料
		2.示例如下:
import requests

url = "http://www.baidu.com/"
headers = {"User-Agent":"Mozilla/5.0"}
# 發請求獲響應
response = requests.get(url,headers=headers)
response.encoding = "utf-8"
# 獲取字串
print(type(response.text))
# 獲取位元組流
print(type(response.content))
# 返回伺服器響應碼
print(response.status_code)
# 返回資料的URL
print(respone.url)
      3、response.encoding 
        一般返回 :ISO-8859-1
		response.encoding = "utf-8"
      4、response.status_code :返回伺服器響應碼
      5、response.url :返回資料的URL地址
    3、get()使用場景
      1、沒有查詢引數
        res = requests.get(url,headers=headers)
      2、有查詢引數: params={}
        注 :params引數必須為字典,自動進行編碼
		見 :09_requests.get.params.py
#09_requests.get.params.py
import requests

headers = {"User-Agent":"Mozilla/5.0"}
url = "http://www.baidu.com/s?"
key = input("請輸入要搜尋的內容:")
params = {"wd":key}

# 自動編碼,自動拼接URL,params必須為字典
res = requests.get(url,params=params,headers=headers)
# 指定utf-8
res.encoding = "utf-8"
print(res.text)
    4、post() 引數名 :data
      1、data = {}
      2、示例 :10_有道翻譯post.py
#有道翻譯post.py
import requests
import json

# 請輸入你要翻譯的內容
key = input("請輸入要翻譯的內容:")
# post方法要求data為字典格式
data = {"i": key,
        "from":"AUTO",
        "to":"AUTO",
        "smartresult":"dict",
        "client":"fanyideskweb",
        "salt":"1540373170893",
        "sign":"a5d9b838efd03c9b383dc1dccb742038",
        "doctype":"json",
        "version":"2.1",
        "keyfrom":"fanyi.web",
        "action":"FY_BY_REALTIME",
        "typoResult":"false"
    }

# 發請求,獲取響應
# url為POST的地址,抓包工具抓到的,此處去掉 _o
url = "http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
headers = {"User-Agent":"Mozilla/5.0"}
# 此處data為form表單資料
res = requests.post(url,data=data,headers=headers)
res.encoding = "utf-8"
html = res.text
# 把json格式字串轉換為Python中字典
r_dict = json.loads(html)
result = r_dict['translateResult'][0][0]["tgt"]
print(result)

#把翻譯後的結果輸出來
# 請輸入要翻譯的內容 :你好
# hello

#{'type': 'ZH_CN2EN', 
# 'errorCode': 0, 
# 'elapsedTime': 7, 
# 'translateResult': 
# [[{'src': '風雲', 'tgt': 'Occasion'}]]
#}
#示例:
#cookie模擬登陸人人網
import urllib.request

url = "http://www.renren.com/967469305/profile"
headers = {
        "Host":"www.renren.com",
        "Connection":"keep-alive",
        "Upgrade-Insecure-Requests":"1",
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "Referer":"http://www.renren.com/",
#        Accept-Encoding: gzip, deflate
        "Accept-Language":"zh-CN,zh;q=0.9",
        "Cookie":"anonymid=jnoaljpk7d3nh2; depovince=BJ; _r01_=1; _de=4DBCFCC17D9E50C8C92BCDC45CC5C3B7; ln_uact=13603263409; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; jebe_key=1b1f4a34-0468-4185-a3b0-6f2c38abc368%7C2012cb2155debcd0710a4bf5a73220e8%7C1540454149943%7C1%7C1540454153787; wp_fold=0; wp=0; jebecookies=2fc339e7-1b51-43ce-bc85-e2dc1f68ee16|||||; JSESSIONID=abcANrnqoMuLshY34pQAw; ick_login=30d0bd58-f6bb-437f-8d0d-6a72ae00e7b7; p=1e1b85cb8dda387a70e400a341c2e9c95; first_login_flag=1; t=4f652cc0a8f3fd50f5c9095c92d4717d5; societyguester=4f652cc0a8f3fd50f5c9095c92d4717d5; id=967469305; xnsid=55bff2d5; loginfrom=syshome"
    }

req = urllib.request.Request(url,headers=headers)
res = urllib.request.urlopen(req)
print(res.read().decode("utf-8"))
#示例:
#貓眼電影top100抓取
import urllib.request
import re
import csv

class MaoyanSpider:
    def __init__(self):
        self.baseurl = "http://maoyan.com/board/4?offset="
        self.headers = {"User-Agent":"Mozilla/5.0"}
        self.page = 1
        self.offset = 0
        
    # 下載頁面
    def loadPage(self,url):
        req = urllib.request.Request(url,headers=self.headers)
        res = urllib.request.urlopen(req)
        html = res.read().decode("utf-8")
        self.parsePage(html)
        
    # 解析頁面
    def parsePage(self,html):
        p = re.compile('<div class="movie-item-info">.*?title="(.*?)".*?<p class="star">(.*?)</p>.*?releasetime">(.*?)</p>',re.S)
        r_list = p.findall(html)
#        print(r_list)
        # [("霸王別姬","張國榮","1994-01-01"),(),()...]
        self.writePage(r_list)
    
    def writePage(self,r_list):
        if self.page == 1:
            with open("貓眼電影.csv","a",newline="") as f:
                writer = csv.writer(f)
                writer.writerow(["電影名稱","主演","上映時間"])
        for r_tuple in r_list:
            with open("貓眼電影.csv","a",newline="") as f:
                # 建立寫入物件
                writer = csv.writer(f)
#                L = list(r_tuple)
                L = [r_tuple[0].strip(),r_tuple[1].strip(),r_tuple[2].strip()]
                # ["霸王別姬","張國榮","1994-01-01"]
                writer.writerow(L)
    
    def workOn(self):
        while True:
            c = input("爬取請按y(y/n):")
            if c.strip().lower() == "y":
                self.offset = (self.page-1)*10
                url = self.baseurl + str(self.offset)
                self.loadPage(url)
                self.page += 1
            else:
                print("爬取結束,謝謝使用!")
                break
                
if __name__ == "__main__":
    spider = MaoyanSpider()
    spider.workOn()     
#示例:
#內涵吧資訊抓取
import urllib.request
import re

class NeihanSpider:
    def __init__(self):
        self.baseurl = "https://www.neihan8.com/njjzw/"
        self.headers = {"User-Agent":"Mozilla/5.0"}
        self.page = 1
        
    # 下載頁面
    def loadPage(self,url):
        req = urllib.request.Request(url,headers=self.headers)
        res = urllib.request.urlopen(req)
        html = res.read().decode("utf-8")
        self.parsePage(html)
        
    # 解析頁面
    def parsePage(self,html):
        p = re.compile('<div class="text-.*?title="(.*?)".*?<div class="desc">(.*?)</div>',re.S)
        r_list = p.findall(html)
        # [("什麼動物...","海豹"),(),()...]
        self.writePage(r_list)
        
    # 儲存頁面
    def writePage(self,r_list):
        for r_tuple in r_list:
            for r_str in r_tuple:
                with open("急轉彎.txt","a",encoding="gb18030") as f:
                    f.write(r_str.strip() + "\n")
            with open("急轉彎.txt","a",encoding="gb18030") as f:
                f.write("\n")
        
    def workOn(self):
        self.loadPage(self.baseurl)
        while True:
            c = input("成功,是否繼續(y/n):")
            if c.strip().lower() == "y":
                self.page += 1
                url = self.baseurl + "index_" +\
                      str(self.page) + ".html"
                self.loadPage(url)
            else:
                print("爬取結束,謝謝使用!")
                break
                
if __name__ == "__main__":
    spider = NeihanSpider()
    spider.workOn()