Python網路爬蟲(正則, 內涵段子,貓眼電影, 鏈家爬取)

weixin_34127717發表於2018-10-30
正規表示式(re模組):
    資料的分類:
        結構化資料
            有固定的格式 如HTML、XML、JSON
        非結構化資料
            圖片、音訊、視訊 這類資料一般儲存為二進位制
    正則:
        使用流程:
            建立編譯物件:p = re.compile("正規表示式")
            對字串匹配:r = p.match("字串")
            獲取匹配結果:print(r.group())
        常用方法:
            match(str)  字串開頭的第一個  返回物件
            search(str) 從頭開始匹配 只匹配一個 返回物件
            group()     從match或search物件中取值
            findall()   所有全域性匹配  返回一個列表
        表示式:
            .   匹配任意字元(除了\n)
            \d  匹配數字
            \s  空白字元
            \S  非空字元
            []  匹配括號內所有內容
            \w  字母、數字、下劃線
            *   前一個出現0次或多次
            ?   0次或1次
            +   一次或多次
            {m} m次
            {m, n} m到n次

        貪婪匹配:
            再整個表示式匹配成功前提下 儘可能多的去匹配*
        非貪婪匹配:
            再整個表示式匹配成功前提下 儘可能少的去匹配*
    示例(貪婪模式和非貪婪模式)

import re

s = """<div><p>年發的斯蒂芬是否</div></p>
<div><p>年發的斯蒂芬是否</div></p>
"""
# 建立編譯物件 貪婪匹配  re.S代表讓.可以匹配\n字元
p = re.compile("<div><p>.*</div></p>", re.S)
# 匹配字串s
r = p.findall(s)
# 結果為一個列表內只有與一個元素
print(r)

# 非貪婪匹配 用?儘可能少的去匹配
p = re.compile("<div><p>.*?</div></p>", re.S)
# 匹配字串s
r = p.findall(s)
# 結果為一個列表內有多個元素
print(r)

    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))


    7、案例1 :內涵段子腦筋急轉彎抓取

# 思路
# 
#  網址 :www.neihan8.com
#   步驟:
#     1、找URL規律
#  第1頁:https://www.neihan8.com/njjzw/
#  第2頁:https://www.neihan8.com/njjzw/index_2.html
#  第3頁:https://www.neihan8.com/njjzw/index_3.html
# 用正則匹配出 題目 和 答案
#   p = re.compile('<div class="text-.*?title="(.*?)".*?<div class="desc">(.*?)</div>',re.S)
# 寫程式碼
#   發請求
#   用正則匹配
#   寫入本地檔案


import urllib.request
import re
import random


class NeihanSpider(object):
    def __init__(self):
        self.baseurl = "http://www.neihan8.com/wenzi/"
        self.headers = {"User-Agent": "Mozilla/5.0"}
        self.page = 1

    # 下載頁面
    def load_page(self, url):
        # 隨機獲取1個User-Agent
        header_list = [{
            "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"},
            {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"},
            {"User-Agent": "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.0)"}]
        headers = random.choice(header_list)
        req = urllib.request.Request(url, headers=headers)
        res = urllib.request.urlopen(req)
        html = res.read().decode("utf-8")
        self.parse_page(html)

    # 解析頁面
    def parse_page(self, html):
        p = re.compile(r'''<div class="text-.*?"title="(.*?)">.*?class="desc">(.*?)</div>''')
        r_list = p.findall(html)
        self.write_page(r_list)

    # 儲存頁面
    def write_page(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")

    # 主函式
    def work_on(self):
        self.load_page(self.baseurl)
        while True:
            c = input("是否繼續...(y/n)")
            if c.strip().lower() == "y":
                self.page += 1
                url = self.baseurl + "index_1.html"
                self.load_page(url)
            else:
                break


if __name__ == "__main__":
    sipder = NeihanSpider()
    sipder.work_on()
 
    貓眼電影top100榜單,存到csv表格檔案中
      網址:貓眼電影 - 榜單 - top100榜
      目標:抓取電影名、主演、上映時間
      知識點講解
        csv模組的使用流程
  開啟csv檔案
    with open("測試.csv","a") as f:
  初始化寫入物件
    writer = csv.writer(f)
  寫入資料
    writer.writerow(列表)

import csv

with open("貓眼.csv", "a") as f:
    # 初始化寫入物件
    writer = csv.writer(f)
    writer.writerow(["霸王別姬", "張國榮"])
    writer.writerow(["唐伯虎點秋香", "周星馳"])

      準備工作
        找URL
  第1頁:http://maoyan.com/board/4?offset=0
  第2頁:http://maoyan.com/board/4?offset=10
  第n頁:
    offset = (n-1)*10
正則匹配
  <div class="movie-item-info">.*?title="(.*?)".*?<p class="star">(.*?)</p>.*?releasetime">(.*?)</p>

import random
import re
import urllib.request
import UserAgent
import csv

class MovieRanking(object):
    def __init__(self):
        self.baseurl = "http://maoyan.com/board/4?offset="
        self.headers = random.choice(UserAgent.headers_list)
        self.page = 0

    def read_page(self, url):
        requuest = urllib.request.Request(url, headers=self.headers)
        response = urllib.request.urlopen(requuest)
        html = response.read().decode("utf-8")
        self.parse_page(html)

    def parse_page(self, html):
        p = re.compile(r'''<p class="name".*?title="(.*?)".*?class="star">(.*?)</p>.*?class="releasetime">(.*?)</p>''', re.S)
        movie_list = p.findall(html)
        self.write_page(movie_list)

    def write_page(self, movie_list):
        for movie in movie_list:
            movie_list = [movie[0].strip(), movie[1].strip(), movie[2].strip()]
            with open("貓眼Top.csv", "a", encoding="utf-8") as f:
                writer = csv.writer(f)
                writer.writerow(movie_list)


    def main_page(self, number):
        i = 0
        while i < number:
            url = self.baseurl + str(self.page)
            self.read_page(url)
            self.page += 1
            i += 1


if __name__ == "__main__":
    movie = MovieRanking()
    movie.main_page(100)


Fiddler常用選單
  Inspector : 檢視抓到的資料包的詳細內容
    分為請求(request)和響應(response)兩部分
  常用選項
Headers :顯示客戶端傳送到伺服器的header,包含客戶端資訊、cookie、傳輸狀態
WebForms :顯示請求的POST資料 <body>
Raw :將整個請求顯示為純文字
請求方式及案例
  GET
  POST
  Cookie模擬登陸
    什麼是cookie、session
      HTTP是一種無連線協議,客戶端和伺服器互動僅僅限於 請求/響應過程,結束後斷開,下一次請求時,伺服器會認為是一個新的客戶端,為了維護他們之間的連線,讓伺服器知道這是前一個使用者發起的請求,必須在一個地方儲存客戶端資訊。
      cookie :通過在客戶端記錄的資訊確定使用者身份
      session :通過在服務端記錄的資訊確定使用者身份
        使用cookie模擬登陸人人網

'''cookie模擬登陸人人網.py'''
import urllib.request

# 步驟:
#     通過抓包工具、F12獲取到cookie(先登陸1次網站)
#     正常發請求
#     url:http://www.renren.com/967469305/profile

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-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"))



requests模組
    安裝(用管理員身份去開啟Anaconda Prompt)
    Anaconda   : conda install requests
    Windows cmd: python -m pip install requests
      ## 以管理員身份去執行pip安裝命令
    常用方法
    get(url,headers=headers) : 發起請求,獲取響應物件
    response屬性
      response.text :返回字串型別
      response.content : 返回bytes型別
     應用場景 :爬取非結構化資料
      response.encoding 
        一般返回 :ISO-8859-1  # latin1
指定編碼:response.encoding = "utf-8"
      response.status_code :返回伺服器響應碼
      response.url :返回資料的URL地址
    get()使用場景
      沒有查詢引數
        res = requests.get(url,headers=headers)
      有查詢引數: params={}
        注 :params引數必須為字典,自動進行編碼
見 :09_requests.get.params.py
    post() 引數名 :data
      data = {}

爬取鏈家二手房

import csv
import re
import requests


class HouseReptile(object):

    def __init__(self):
        self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60"}
        self.base_url = "https://jn.lianjia.com/ershoufang/pg"
        self.pg = 0
        print("初始化~")

    def read_house(self, url):
        print("讀取資料")
        response = requests.get(url, self.headers)
        self.parse_house(response.text)

    def parse_house(self, html):
        print("開始解析資料")
        # 詳情頁  標題  小區名  規格  樓層 釋出時間  總價 單價
        mate = re.compile('''<div class="title"><a class="" href="(.*?)".*?data-is_focus="" data-sl="">(.*?)</a>.*?data-el="region">(.*?)</a> (.*?)<.*?</span>(.*?)<.*?starIcon"></span>(.*?)<.*?<span>(\d+)</span>萬.*?<span>(.*?)</span>''', re.S)
        house_list = mate.findall(html)
        self.write_house(house_list)


    def write_house(self, house_list):
        for house in house_list:
            with open("連結二手房.csv", "a", newline="", encoding="utf-8") as f:
                writer = csv.writer(f)
                house = [
                    house[0].strip(),
                    house[1].strip(),
                    house[2].strip(),
                    house[3].strip(),
                    house[4].strip(),
                    house[5].strip(),
                    house[6].strip(),
                    house[7].strip()
                ]
                writer.writerow(house)


    def crawl_house(self, number):
        if self.pg == 0:
            with open("連結二手房.csv", "a", newline="", encoding="utf-8") as f:
                writer = csv.writer(f)
                writer.writerow([
                    "房屋詳情連結",
                    "標題",
                    "小區名",
                    "規格",
                    "樓層",
                    "釋出時間",
                    "總價(萬)",
                    "單價"
                ])

        for i in range(0, number):
            self.pg += 1
            url = self.base_url + str(self.pg)
            print("開始爬取:", url)
            self.read_house(url)


if __name__ == "__main__":
    house = HouseReptile()
    house.crawl_house(3)



        
      












相關文章