學習Python的第四天

爬蟲

網絡爬蟲是一個自動提取網頁的程序,它為搜索引擎從萬維網上下載網頁,是搜索引擎的重要組成。傳統爬蟲從一個或若干初始網頁的URL開始,獲得初始網頁上的URL,在抓取網頁的過程中,不斷從當前頁面上抽取新的URL放入隊列,直到滿足系統的一定停止條件。

提取本地html中的數據

1.新建html文件
2.讀取
3.使用 lxml 中的 xpath 語法進行提取
比如:使用lxml提取h1標簽中的內容

from lxml import html
# 讀取html文件
with open('./index.html', 'r', encoding='utf-8') as f:
    html_data = f.read()
    # print(html_data)
    #解析html文件,獲得selector對象
    selector = html.fromstring(html_data)
    # selector 中調用xpath方法
    # 要獲取標簽中的內容,末尾要添加text()
    h1 = selector.xpath('/html/body/h1/text()')
    print(h1[0])

    # // 可以代表從任意位置出發
    # //標簽1[@屬性=屬性值]/標簽2[@屬性=屬性值]....
    a = selector.xpath('//div[@id="container"]/a/text()')
    print(a[0])
    # 獲取p標簽的內容
    p = selector.xpath('//div[@id="container"]/p1/text()')
    print(p[0])
    # 獲取屬性
    link = selector.xpath('//div[@id="container"]/a/@href')
    print(link[0])

執行結果如下


網絡爬蟲使用requests庫

在使用python爬蟲爬取數據的時候,經常會遇到一些網站的反爬蟲措施,一般就是針對于headers中的User-Agent,如果沒有對headers進行設置,User-Agent會聲明自己是python腳本,而如果網站有反爬蟲的想法的話,必然會拒絕這樣的連接。而修改headers可以將自己的爬蟲腳本偽裝成瀏覽器的正常訪問,來避免這一問題。

import requests
from lxml import html
url = 'http://www.dangdang.com'
response = requests.get(url)
print(response)
# 獲取str類型的響應 根據http頭部對響應的編碼做出有根據的推測
print(response.text)
# 獲取bytes類型的響應
print(response.content)
# 獲取響應頭
print(response.headers)
# 獲取狀態碼
print(response.status_code)

print(response.encoding)
沒有添加請求頭
resp = requests.get('https://www.zhihu.com')
print(resp.status_code)
使用字典定義請求頭
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"}
resp = requests.get('http://www.dangdang.com', headers = header)
print(resp.status_code)

運行結果大致如下:



也可以將爬到的html頁面寫入本地

import requests
def spider_dangdang(isbn):
    book_list = []
    # 目標站點地址
    url = 'http://search.dangdang.com/?key={}&act=input'.format(isbn)
    # 獲取站點str類型的響應
    header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"}

   resp = requests.get(url, headers=header)
    html_data = resp.text
    # 將html頁面寫入本地
    with open('dangdnag.html', 'w', encoding='utf-8') as f:
        f.write(html_data)
spider_dangdang(9787115428028)

執行程序之后,文件夾中就會生成爬到的html文檔
$JOOAMX01JC)I({5ZQ1W}9F.jpg

我們還可以獲取目標站點的詳細信息

import requests
from  lxml import html
import pandas as pd
from matplotlib import pyplot as plt
plt.rcParams["font.sans-serif"] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

def spider_dangdang(isbn):
    book_list = []
    # 目標站點地址
    url = 'http://search.dangdang.com/?key={}&act=input'.format(isbn)
    # 獲取站點str類型的響應
    header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"}

    resp = requests.get(url, headers=header)
    html_data = resp.text
    # 將html頁面寫入本地
    # with open('dangdnag.html', 'w', encoding='utf-8') as f:
    #     f.write(html_data)
        # 提取目標站的信息
    selector = html.fromstring(html_data)
    ul_list = selector.xpath('//div[@id="search_nature_rg"]/ul/li')
    print('您好,一共有{}家店鋪售賣此圖書'.format(len(ul_list)))

   # 遍歷ul_list
    for li in ul_list:

        #  圖書名稱
        title = li.xpath('./a/@title')[0].strip()
        print('圖書名稱:', title)

        #  圖書價格
        price = li.xpath('./p[@class="price"]/span[@class="search_now_price"]/text()')[0]
        price = float(price.replace('¥', ''))
        print('圖書價格:', price)

        #  圖書購買鏈接
        link = li.xpath('./a/@href')[0]
        print('圖書購買鏈接:', link)
        # 圖書賣家名稱
        store = li.xpath('./p[@class="search_shangjia"]/a[1]/text()')
        # if len(store) == 0:
        #     store = "當當自營"
        # else:
        #     store = store[0]
        # price = price.replace('¥', '')
        store = "當當自營" if len(store) == 0 else store[0]
        print('圖書賣家名稱:', store)
        print('')
spider_dangdang(9787115428028)

可以得到下面的結果


我們可以追加一下代碼按照價格進行排序,并遍歷圖書信息

#按照價格進行排序
    book_list.sort(key=lambda x: x['price'])

    # 遍歷book_list
    for book in book_list:
         print(book)

可以得到下面的結果


用下面的代碼,我們可以將數據存儲成csv文件

df = pd.DataFrame(book_list)
    df.to_csv('dangdang.csv')

記得導入 pandas

import pandas as pd

執行程序,文件夾中就會生成相應的csv文件


也能用柱狀圖展示價格最低的前十家

top10 = [book_list[i] for i in range(10)]
    x = [x['store'] for x in top10]
    print(x)
    y = [x['price'] for x in top10]
    print(y)
    # plt.bar(x, y)
    plt.barh(x, y)
    plt.show()

記得導入包,否則會報錯

from matplotlib import pyplot as plt
plt.rcParams["font.sans-serif"] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

練習

提取https://movie.douban.com/cinema/later/chongqing網站以下信息,并且根據信息完成3,4效果
1.電影名,上映日期,類型,上映國家,想看人數
2.根據想看人數進行排序
3.繪制即將上映電影國家的占比圖
4.繪制top5最想看的電影

import requests
from  lxml import html
from matplotlib import pyplot as plt
plt.rcParams["font.sans-serif"] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def spider_douban():
    movies_list = []
    counts = {}
    # 目標站點地址
    url = 'https://movie.douban.com/cinema/later/chongqing/'
    # 獲取站點str類型的響應
    header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"}

    resp = requests.get(url, headers=header)
    html_data = resp.text
    # 將html頁面寫入本地
    # with open('douban.html', 'w', encoding='utf-8') as f:
    #     f.write(html_data)
        # 提取目標站的信息
    selector = html.fromstring(html_data)
    ul_list = selector.xpath('//div[@id="showing-soon"]/div')
    print('您好,一共有{}部電影即將上映'.format(len(ul_list)))

    # 遍歷ul_list
    for li in ul_list:

        #  電影名
        title = li.xpath('./div[@class="intro"]/h3/a/text()')[0]
        print('電影名:', title)
    #
    #
        #  上映日期
        date = li.xpath('./div[@class="intro"]/ul/li[1]/text()')[0]
        # price = float(price.replace('¥', ''))
        print('上映日期:', date)
    #
        #  類型
        type = li.xpath('./div[@class="intro"]/ul/li[2]/text()')[0]
        types = str(type.replace('/', ','))
        print('類型:', types)

        #  上映國家
        nation = li.xpath('./div[@class="intro"]/ul/li[3]/text()')[0]
        print('上映國家:', nation)

        #  想看人數
        want_num = li.xpath('./div[@class="intro"]/ul/li[4]/span/text()')[0]

        want_num = int(want_num.replace('人想看', ''))
        print('想看人數:', want_num)
        # 添加每一部電影的信息
        movies_list.append({
            'title': title,
            'date': date,
            'types': types,
            'nation': nation,
            'want_num': want_num
        })

    for nation in movies_list:
        counts[nation['nation']] = counts.get(nation['nation'], 0) + 1
    print(counts)
    # 4.排序 [(), ()]
    items = list(counts.items())
    items.sort(key=lambda x: x, reverse=True)
    print(items)
    nations = []
    cishu = []
    for i in range(4):
        #序列解包
        na, count = items[i]
        # print(role, count)
        nations.append(na)
        cishu.append(count)

    explode = [0.1, 0, 0, 0]
    colors = ['red', 'purple', 'blue', 'yellow']
    plt.pie(cishu, explode=explode, colors=colors, shadow=True, labels=nations, autopct='%1.1f%%')
    plt.legend(loc=2)  # 圖例位置
    plt.axis('equal')
    plt.show()
    # 按照價格進行排序
    movies_list.sort(key=lambda x: x['want_num'], reverse=True)
    # 遍歷book_list
    for movie in movies_list:
        print(movie)
    # 展示最想看的top5
    top5 = [movies_list[i] for i in range(5)]
    x = [x['title'] for x in top5]
    print(x)
    y = [x['want_num'] for x in top5]
    print(y)
    plt.bar(x, y)
    # plt.barh(x, y)
    plt.show()


spider_douban()

可以得到下面的結果:


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容