天天看點

爬蟲學習—疫情篇

一、理論

 1、爬蟲的分類:

    通用爬蟲:搜尋引擎的爬蟲

    聚焦爬蟲:針對特定網站的爬蟲

可以看出來了,我們一般用的都是聚焦爬蟲吧

 2、聚焦爬蟲的工作流程:

    (1)明确URL(請求位址,明确爬什麼)

    (2)發送請求,擷取響應資料

    (3)儲存相應資料,提取有用資訊

    (4)處理資料(存儲、使用)

 3、雙向爬取。

首先我們來熟悉兩個基礎技術名詞:橫向爬取 和縱向爬取。。

    橫向爬取:所謂橫向爬取,是指在爬取的網站頁面中,以“頁”為機關,找尋該網站分頁器規律。一頁一頁的爬取網

站資料資訊,大多數網站,采用分頁管理模式,針對這類網站,首先要确立橫向爬取方法。。

    縱向爬取:縱向爬取,是指在一個頁面内,按不同的“條目”為機關。找尋各條目之間的規律。一條一條的爬取一個

網頁中的資料資訊。也就是同時爬取一個頁面内不同類别資料。

二、

爬蟲由:

(1)發送請求,擷取響應——requests

(2)解析資料——beautifulsoup、re

(3)儲存資料——json

<一>、requests(發送請求,擷取響應)

requests是一個簡單的pythonHTTP請求庫,requests的作用是發送請求擷取相應資料

##1.導入子產品

import requests

##2.發送請求,擷取響應

response=requests.get('https://www.baidu.com/')

##3.擷取響應資料

#print(response.encoding)#ISO-8859-1

response.encoding='utf8'

#print(response.text)

print(response.content.decode(encoding='utf8'))

Response.encoding -編碼格式

Response.encoding-指定編碼格式

Response.text-按照指定編碼格式解碼輸出

可以把前兩個合并成一句Response.content.decode(encoding='gbk')。有的網頁不是utf-8,可以指定格式用來解碼,例gbk

response(響應)常見屬性:

    response.text:響應體str類型

    response.econding:二進制轉換字元使用的編碼

    response.content:響應體bytes類型

<二>、BeautifulSoup

BeautifulSoup是一個可以從HTML或XML檔案中提取資料的python庫

<1>、安裝BeautifulSoup(用Spyder應該是不用安裝的)

pip install bs4

pip install lxml

<2>、BeautifulSoup對象:代表要解析整個文檔樹,它支援周遊文檔樹和搜尋文檔樹中描述的大部分的方法

<3>建立BeautifulSoup對象

#1、導入子產品

from bs4 import BeautifulSoup

#2、建立BeautifulSoup對象

soup=BeautifulSoup("<html>data</html>

#3、建立BeautifulSoup對象

    soup=BeautifulSoup(html_doc,'lxml')

    #4、查找文檔中的title标簽

    title=soup.find('title')

    #5、查找文檔中a(需要的)标簽

    a=soup.find('a')

    print(a)#隻輸出第一個a标簽

    a_s=soup.find_all('a')

    print(a_s)#輸出所有的a标簽

2、根據屬性查找

    #方法一、通過命名參數進行指定的

    a=soup.find(id='link1')

    #方法二、使用attrs來指定屬性字典,進行查找

    a=soup.find(attrs={'id':'link1'}) (方法二适用性更強)

3、根據文本查找

    text=soup.find(text='陳雨菲')

<5>、BeautifulSoup對象的find方法—Tag對象

Tag對象對應于原始文檔中的XML或HTML标簽, Tag 對象Tag有很多方法和屬性,可用周遊文檔樹和搜尋文檔樹以及擷取标簽内容

Tag對象常用屬性

    name:擷取标簽名稱

    attrs:擷取标簽所有屬性的鍵和值

    text:擷取标簽的文本字元串

#擷取a标簽的Tag對象

a=soup.find('a')

print(a)

#Tag的name屬性,擷取标簽名

print('标簽名',a.name)

#Tag的attrs屬性,标簽所有屬性的鍵和值

print('所有屬性',a.attrs)

#Tag的text屬性,擷取标簽的文本字元串

print('标簽文本',a.text)

三、正規表達式

1、概念:正規表達式是一種字元串比對的模式(pattern)

2、作用:從某個字元串中提取符合某種條件的子串

3、文法

    1..比對除換行符(\n)以外的所有字元

    2.\d比對[0-9]的數字

    3.\w比對字母數字_和中文;

    4*前面的一個比對模式出現0次或多次

    5+前面的一個比對模式出現1次或多次

    6?前面的一個比對模型出現0或1次

 import re

rs=re.findall("a\nc", "a\nc")

print(rs)#['a\nc']

rs=re.findall("a\\\\nc", "a\\nc")

print(rs)#['a\\nc']

rs=re.findall(r"a\nc", "a\nc")

print(rs)#['a\nc']

 正則中使用r原始字元串,能夠忽略轉義符号帶來的影響

帶比對的字元串中有多少個\,r原串正則中就添加多少個\即可

 4、提取json字元串http://ncov.dxy.cn/ncovh5/view/pneumonia

 import requests

from bs4 import BeautifulSoup

import re

#1發送請求,擷取響應

response=requests.get('http://ncov.dxy.cn/ncovh5/view/pneumonia')

#2從響應中擷取資料

page=response.content.decode()

#3建構BeautifulSoup對象

soup=BeautifulSoup(page,'lxml')

#print(soup)

#4根據id查找,包含全國疫情資訊的标簽

#st=soup.find(id='getAreaStat')

st=soup.find(id='getListByCountryTypeService2true')

#print(st)

#5擷取标簽中文本内容

te=st.string#st.text不行

print(te)

#6提取json字元串

json_str=re.findall(r'(

.∗

.∗

)', te)

print(json_str)

5、總結

(1)正規表達式是一種字元串比對的模式(pattern),在爬蟲中主要用于從某個字元串中

提取符合某種條件的子串

(2)常見文法:.[] \d\w*+?

(3)refindall()查找字元串所有與正則比對的子串傳回一個清單,如果沒有找到傳回空列

(4)refindall()如果正則中沒有分組,傳回與整個正則比對的子串,如果正則中有分組,隻返

回與分組比對的子串,分組兩邊的正則是用于定位的.

(5)正則中使用r原串就是為了消除轉移符(\)的影響,也就是比對的字元串中,有多少個轉

移符,r原串的正則中寫幾個\就可以了.

6、JSON轉Python(json.loads())

###JSON轉Python

import json

#1、json字元串,轉換Python類型資料

#1.1準備json字元串

str='{"provinceName":"台灣","provinceShortName":"台灣","currentConfirmedCount":"2029"}'

#1.2把json字元串轉換為python類型的資料

python1=json.loads(str)

#1.3輸出結果

print(python1)

#2、json格式檔案 轉換python類型資料

#2.1打開檔案對象

with open('data11.json',encoding='utf-8') as f:

    #2.2把檔案中的json格式内容轉換python類型資料

    python2=json.load(f)

    #2.3輸出

    print(python2)

    print(type(python2))

 7、Python轉Json(json.dumps())

##python轉換為json

#1python類型資料轉換為json字元串json.dumps(obj)

import json

str='{"provinceName":"台灣","provinceShortName":"台灣","currentConfirmedCount":"2029"}'

json1=json.dumps(str)

print(json1)#"{\"provinceName\":\"\u53f0\u6e7e\",\"provinceShortName\":\"\u53f0\u6e7e\",\"currentConfirmedCount\":\"2029\"}"

json2=json.dumps(str,ensure_ascii=False)

print(json2)#"{\"provinceName\":\"台灣\",\"provinceShortName\":\"台灣\",\"currentConfirmedCount\":\"2029\"}"

#2Python類型資料以json格式寫入檔案json.dump(obj,fp)

with open('data11.json',mode='w') as f:

    python1=json.loads(str)

    #以json格式寫入檔案,寫入的内容不包含非ASCII字元

    a=json.dump(python1,f)

    print(a)

    #以json格式寫入檔案,寫入的内容包含非ASCII字元

    b=json.dump(python1,f,ensure_ascii=False)

    print(b)

四、案例——統計今日(2021/8/3)以來的所有疫情資訊

###########案例、統計2021/8/4以來各國的疫情資訊###########

import requests

from bs4 import BeautifulSoup

import re

import json

from tqdm import tqdm#進度條

class CoronaVirusSpider(object):

    #類CoronaVirusSpider

    def __init__(self):

        self.home_url='http://ncov.dxy.cn/ncovh5/view/pneumonia'

    def get_content_from_url(self,url):

        #發送請求,擷取響應

        response=requests.get(url)

        #從響應中擷取資料

        return response.content.decode()

    def parse_home_page(self,home_page):

        #解析首頁内容,擷取解析後的python資料

        #建構BeautifulSoup對象

        soup=BeautifulSoup(home_page,'lxml')

        #根據id查找,包含全國疫情資訊的标簽

        script=soup.find(id='getListByCountryTypeService2true')

        #擷取标簽中文本内容

        text=script.string

        #提取json字元串

        json_str=re.findall(r'(\[.+\])',text)[0]

        #把json轉換為python

        data=json.loads(json_str)

        return data

    def save(self,data,path):

        #儲存資料

        with open(path,'w',encoding='utf-8') as fp:

            json.dump(data,fp,ensure_ascii=False)

    def crawl_last_day_corona_virus(self):

        #爬取采集最近一天的各國疫情資訊

        #1、發送請求,擷取首頁内容

        home_page=self.get_content_from_url(self.home_url)

        #2、解析首頁内容,擷取最近一天的各國疫情資料

        last_day_corona_virus=self.parse_home_page(home_page)

        #3、儲存資料

        self.save(last_day_corona_virus,'last_day_corona_virus.json')

    def crawl_corona_virus(self):

        #采集各國疫情資料

        #1、加載疫情資料

        with open('last_day_corona_virus.json',encoding='utf-8') as fp:

            last_day_corona_virus=json.load(fp)

        #print(last_day_corona_virus)#得到清單資料

        corona_virus=[]#定義清單,用于存儲各國從1、23以來的疫情資料

        #2、周遊各國疫情資料,擷取統計的URL

        for country in tqdm(last_day_corona_virus,'采集1.23以來的各國疫情資訊'):

        #for country in last_day_corona_virus:

            #3、發送請求,擷取json資料

            statistics_data_url=country['statisticsData']

            statistics_data_json_str=self.get_content_from_url(statistics_data_url)

            #4、把json資料轉換為python類型的資料,添加到清單中

            statistics_data=json.loads(statistics_data_json_str)['data']

            #print(statistics_data)

            for one_day in statistics_data:

                one_day['provinceName']=country['provinceName']

            #print(statistics_data)

            corona_virus.extend(statistics_data)#放到清單

            #5、把清單以json格式儲存為檔案

        self.save(corona_virus,'corcona_virus.json')

    def run(self):

        #self.crawl_last_day_corona_virus()#開始運作這個生成last_day_corona_virus.json

        self.crawl_corona_virus()

if __name__=='__main__':

    spider=CoronaVirusSpider()

    spider.run()