<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          送書 | 聊聊陽光問政

          共 8330字,需瀏覽 17分鐘

           ·

          2021-11-03 16:24


          大家好,我是啃書君!

          正所謂,民生無小事,今日多關(guān)注,今天我們利用多線程來爬取陽光問政,關(guān)注一下老百姓需要解決什么問題。

          線程

          什么是線程

          線程是輕量級(jí)進(jìn)程,是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位,它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位。

          其生命周期可以分為五個(gè)狀態(tài)——新建、就緒、運(yùn)行、阻塞、終止,如下圖所示:

          97fdb752a2c6e59308b1d660c3357d38.webp
          • 新建狀態(tài):新創(chuàng)建的線程在調(diào)用 start() 方法之前,不會(huì)得到執(zhí)行;
          • 就緒狀態(tài):新建狀態(tài)的線程調(diào)用 start() 方法后,該線程就轉(zhuǎn)換到就緒狀態(tài),當(dāng)獲取到CPU資源就可以執(zhí)行;
          • 運(yùn)行狀態(tài):就緒狀態(tài)的線程得到了 CPU資源,并開始執(zhí)行 target 參數(shù)執(zhí)行的目標(biāo)函數(shù)或者 run() 方法;
          • 阻塞狀態(tài):當(dāng) CPU 對(duì)多個(gè)線程進(jìn)行調(diào)度時(shí),對(duì)于獲得 CPU 調(diào)度卻沒有執(zhí)行完畢的線程,該線程就進(jìn)入阻塞狀態(tài);
          • 終止?fàn)顟B(tài):線程執(zhí)行結(jié)束、發(fā)生異常(Exception)或錯(cuò)誤(Error),線程就會(huì)進(jìn)入終止?fàn)顟B(tài)。

          線程創(chuàng)建

          創(chuàng)建線程可以分為五步:編寫執(zhí)行程序、創(chuàng)建線程類、在線程類run方法中調(diào)用要執(zhí)行的程序、開啟線程和等待線程結(jié)束。

          編寫執(zhí)行程序

          import time
          def print_time(threadName):
              for i in range(5):
                  time.sleep(0.5)
                  timestamp = time.time()
                  date = time.localtime(timestamp)
                  Now_date = time.strftime('%Y-%m-%d %H:%M:%S', date)
                  print ("%s: %s" % (threadName, Now_date))

          在執(zhí)行程序中,我們通過time來獲取當(dāng)前系統(tǒng)時(shí)間,由于程序執(zhí)行速度是很快的,所以我們通過time.sleep()方法讓程序休眠0.5秒,這樣我們就可以看到線程的交替執(zhí)行。

          創(chuàng)建線程類

          import threading
          class myThread (threading.Thread):
              def __init__(self, name):
                  super(myThread,self).__init__()
                  self.name = name
              def run(self):
                  pass

          首先導(dǎo)入線程模塊threading,創(chuàng)建myThread()線程類并通過threading.Thread來繼承線程屬性,調(diào)用super()方法并初始化name變量。

          run()方法

          def run(self):
              print ("開始線程:" + self.name)
              print_time(self.name)
              print ("退出線程:" + self.name)

          在run方法中,我們通過調(diào)用print_time()方法并傳入self.name參數(shù)來執(zhí)行第一步編寫的執(zhí)行程序。

          開啟、等待線程

          線程類和執(zhí)行程序都寫好了,接下來開啟線程并等待線程結(jié)束,具體代碼如下所示:

          thread1 = myThread("Thread-1")
          thread2 = myThread("Thread-2")

          thread1.start()
          thread2.start()
          thread1.join()
          thread2.join()
          print ("退出主線程")

          這里我們創(chuàng)建了兩個(gè)線程,首先通過實(shí)例化線程類myThread()并傳入線程名,調(diào)用start()方法使線程處于就緒狀態(tài),再調(diào)用join()方法等待線程結(jié)束。

          運(yùn)行結(jié)果如下所示:

          a0242252f01137960445433cd3423ca3.webp實(shí)戰(zhàn)分析

          首先進(jìn)入陽光問政最新問政網(wǎng)頁并打開開發(fā)者模式,如下圖所示:

          828fe7c44a21d0904089c04c27fdf833.webp

          這個(gè)網(wǎng)站比較簡(jiǎn)單,網(wǎng)頁的URL鏈接最后一個(gè)數(shù)字就是它的頁碼,所以我們構(gòu)造url鏈接時(shí),可以這樣:

          for i in range(1,6):
           url=f'http://wzzdg.sun0769.com/political/index/politicsNewest?id=1&page={i}'

          這樣就可以獲取多頁數(shù)據(jù)了,在源代碼中也有我們想要的詳情網(wǎng)頁url鏈接,其存放在上圖的右邊紅框中。

          隨機(jī)打開一個(gè)問政問題并打開開發(fā)者模式,如下圖所示:

          4e609885232130aa323f81930d491419.webp

          可以發(fā)現(xiàn)該url為http://wzzdg.sun0769.com/political/politics/index?id=529559,對(duì)比上上圖的詳情網(wǎng)頁url,只需要在獲取到的url鏈接前面添加http://wzzdg.sun0769即可。

          詳情網(wǎng)頁也很簡(jiǎn)單,我們想要的數(shù)據(jù)在源代碼中也有,所以我們待會(huì)只要獲取URL鏈接頁面的源代碼即可獲取到所有數(shù)據(jù)。

          實(shí)戰(zhàn)演練

          在實(shí)戰(zhàn)演練中,我們首先通過編寫單線程爬蟲來爬取陽光問政的數(shù)據(jù),再通過多線程程序執(zhí)行單線程爬蟲。

          單線程爬蟲

          獲取詳情網(wǎng)頁url

          首先獲取詳情網(wǎng)頁的url鏈接,主要代碼如下所示:

          import requests
          import parsel
          import pymysql
          def get_link():
              for i in range(1,6):
                  url=f'http://wzzdg.sun0769.com/political/index/politicsNewest?id=1&page={i}'
                  response=requests.get(url,headers=headers)
                  Xapth=parsel.Selector(response.text)
                  f = open('url.txt''a', encoding='utf-8')
                  ul_list = Xapth.xpath('//html/body/div[2]/div[3]/ul[2]/li')
                  for li in ul_list:
                          url_href='https://wzzdg.sun0769.com/'+li.xpath('./span[3]/a/@href').extract_first()
                          f.write(url_href)
                          f.write('\n')
                          get_data(url_href)

          我們一共獲取5頁數(shù)據(jù),每頁數(shù)據(jù)有15條詳情網(wǎng)頁的URL鏈接,通過requests.get()方法發(fā)出網(wǎng)絡(luò)請(qǐng)求,并通過parsel.Selector()方法來解析響應(yīng)的文本數(shù)據(jù),最后將獲取到的url鏈接傳入到自定義get_data()方法。

          注意:這里我們把url鏈接保存在一個(gè)txt文本中,方便我們?cè)诙嗑€程里使用所有詳情網(wǎng)頁的url鏈接。

          獲取詳情網(wǎng)頁數(shù)據(jù)

          獲取詳情網(wǎng)頁的url后,接下來就獲取其內(nèi)容了,具體代碼如下所示:

          def get_data(i):
              response=requests.get(i,headers=headers)
              Xapth=parsel.Selector(response.text)
              data={}
              data['number_id']=Xapth.xpath('/html/body/div[3]/div[2]/div[2]/div[1]/span[4]/text()').extract_first().replace('編號(hào):','')
              data['state_now']=Xapth.xpath('/html/body/div[3]/div[2]/div[2]/div[1]/span[3]/text()').extract_first().replace('狀態(tài):','').strip()
              data['PoliticalTitle']=Xapth.xpath('/html/body/div[3]/div[2]/div[2]/p/text()').extract_first()
              data['PoliticalTime']=Xapth.xpath('/html/body/div[3]/div[2]/div[2]/div[1]/span[2]/text()').extract_first().replace('發(fā)布日期','')
              data['url_href']=i
              data['text']=Xapth.xpath('/html/body/div[3]/div[2]/div[2]/div[2]/pre/text()').extract_first().replace('\n','').replace('\r','')
              saving_scenery_data(list(data.values()))

          獲取詳情網(wǎng)頁的數(shù)據(jù)和獲取url鏈接代碼差不多,這里我就不一一解釋了,最后我們把數(shù)據(jù)傳遞到自定義方法saving_sunshine_data()中。

          保存數(shù)據(jù)

          這次數(shù)據(jù)我們保存在MySQL數(shù)據(jù)庫中,主要代碼如下圖所示:

          def saving_scenery_data(srr):
              db = pymysql.connect(host=host, user=user, password=passwd, port=port, db='Politics')
              cursor = db.cursor()
              sql = 'insert into problem_data(number_id, state_now, PoliticalTitle, PoliticalTime, url_href,text) values(%s,%s,%s,%s,%s,%s)'
              try:
                  cursor.execute(sql,srr)
                  db.commit()
              except:
                  db.rollback()
              db.close()

          首先連接數(shù)據(jù)庫,通過cursor()方法獲取游標(biāo),再通過.execute()方法執(zhí)行單條的sql語句,執(zhí)行成功后返回受影響的行數(shù),然后關(guān)閉數(shù)據(jù)庫連接。當(dāng)保存的數(shù)據(jù)不成功,就調(diào)用rollback()方法,撤消當(dāng)前事務(wù)中所做的所有更改,并釋放此連接對(duì)象當(dāng)前使用的任何數(shù)據(jù)庫鎖。

          啟動(dòng)程序

          好了,主要代碼已經(jīng)寫好了,接下來編寫啟動(dòng)程序的代碼,主要代碼如下圖所示:

          if __name__ == '__main__':
              t1=time.time()
              get_link()
              t2=time.time()
              print(t2-t1)

          這里我們通過time.time()方法來獲取爬蟲程序的執(zhí)行時(shí)間。

          運(yùn)行結(jié)果如下圖所示:

          bfb3cb6c1c963894b35963f019400ba6.webp

          從結(jié)果來看,單線程爬取數(shù)據(jù)用了16秒,接下來編寫多線程來爬取數(shù)據(jù)。

          多線程爬蟲

          剛才單線程爬蟲的文件名為yangguang.py,可以直接調(diào)用單線程爬蟲方法來編寫多線程爬蟲,首先創(chuàng)建多線程爬蟲類,主要代碼如下所示:

          import yangguang
          import threading
          import time
          f=open('url.txt',mode='r')
          class mythread(threading.Thread):
              def __init__(self,f):
                  super(mythread,self).__init__()
                  self.f=f
              def run(self)->None:
                  for i in self.f:
                      yangguang.get_data(i)

          首先導(dǎo)入單線程爬蟲yangguang.py文件,打開剛才單線程爬蟲保存的txt文件,再創(chuàng)建mythread()類并初始化線程類,重寫run()方法,通過for循環(huán)把txt文件中的url讀取并傳遞在單線程爬蟲yangguang.get_data()方法中。

          好了,多線程類寫好了,接下來編寫執(zhí)行代碼,主要代碼如下所示:

          if __name__ == '__main__':
              t1=time.time()
              yangguang.create_db()
              threads = [mythread(f) for i in range(10)]
              for thread in threads:
                  thread.start()
              for thread in threads:
                  thread.join()
              t2=time.time()
              print(t2-t1)

          這里我們創(chuàng)建了10個(gè)線程,運(yùn)行結(jié)果如下所示:

          5420296efc1d4130a209b7da3f6743a3.webp 9f7d132b5ad4b0c6c0753f256cb54bbe.webp

          開啟十個(gè)線程來爬取數(shù)據(jù),一共用了2.4秒,大大提高了爬蟲效率。

          好了,多線程爬取陽光問政就講到這里了,感謝觀看?。。?/p>



          送書

          又到了每周三的送書時(shí)刻,今天給大家?guī)淼氖恰?span style="font-weight:700;">菜鳥輕松拿offer:軟件測(cè)試工程師面試秘笈》,本書以測(cè)試基礎(chǔ)知識(shí)為主,非常適合應(yīng)屆畢業(yè)生、初入門軟件測(cè)試的人員。對(duì)于轉(zhuǎn)行進(jìn)入測(cè)試行業(yè)的人員,本書也非常適合。本書也可用于教材,指導(dǎo)測(cè)試人員找工作,與面試官進(jìn)行交流。作為一本參考書,也適合面試官閱讀,以便于對(duì)求職者進(jìn)行篩選。


          本書特色

          實(shí)用性,接地氣。總結(jié)真實(shí)小例,引出實(shí)用技巧,幫助讀者提高面試成功率。融入百位測(cè)試人員的面試總結(jié)。示例豐富,每一個(gè)面試點(diǎn)都有對(duì)應(yīng)的示例。對(duì)立角度解析,從面試者和面試官兩方面對(duì)問題進(jìn)行解析。形色兼具,外在優(yōu)雅與內(nèi)在實(shí)力相結(jié)合,征服面試官。點(diǎn)擊閱讀原文查看本書詳情哦!


          公眾號(hào)回復(fù):送書 ,參與抽獎(jiǎng)(共5本)

          點(diǎn)擊下方回復(fù):送書  即可!


          大家如果有什么建議,歡迎掃一掃二維碼私聊小編~回復(fù):加群 可加入Python技術(shù)交流群


          瀏覽 129
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  做爱视频无码 | 影音先锋看AV | 免费观看高清无码 | 黄色成人在线免费 | 男人天堂亚洲天堂 |