Python網路爬蟲——模擬登陸爬取網站資料並載入到excl表格裡

life4711發表於2016-04-11

對於需要登陸的網站用Python寫爬蟲的時候需要模擬登陸上去,才能得到想要的介面。

偶然的一個機會,以前的輔導員找到我,想寫一個爬取網路表格到本地excl表格並能支援獲取分頁資料的小程式,碰巧以前寫過爬蟲,這樣一來又深入的理解了一下。前段時間忙著面試一直沒抽出時間,今天花了一天的功夫算是搞出來了。寫一個部落格,以後查詢時方便,也希望能給同樣再寫爬蟲的童鞋一點幫助!

模擬登陸首先要分析一下瀏覽器給伺服器傳送的包,就需要有一個抓包程式,推薦大家使用:Fiddler4。下載安裝之後,在開啟Fiddler時訪問網頁就能捕獲包文,十分方便,同時它也能捕獲Python的包文,對除錯時很有幫助。

整個流程就是模擬瀏覽器給伺服器發包,然後將將需要的檔案從瀏覽器獲取,通過正規表示式將所需要的內容挖出來,然後就是儲存到excl表格裡了。對於正則表達是部分是Python的基礎,我就不重複造輪子了,推薦百度一下。另外值得一提的就是,將資料儲存到excl裡和記事本里不一樣,需要特殊處理一下。請參考以下程式碼:

#encoding:utf8
import xlrd
import xlwt

class OperExcel():
  #讀取Excel表
  def rExcel(self,inEfile,outfile):
    rfile = xlrd.open_workbook(inEfile)
    #建立索引順序獲取一個工作表
    table = rfile.sheet_by_index(0)
    #其他方式
    #table = rfile.sheets()[0]
    #table = rfile.sheet_by_name(u'Sheet1')

    #獲取整行,整列的值
    table.row_values(0)
    table.col_values(0)

    #獲取行數和列數
    nrows = table.nrows - 1
    ncols = table.ncols

    #迴圈獲取列表的資料
    #for i in range(nrows):
    #  print table.row_values(i)
    wfile = open(outfile,'w')
    #獲取第一列中的所有值
    for i in range(nrows):
      #table.cell(i,0).value獲取某一單元格的值
      wfile.write(table.cell(i,0).value.encode('utf8') + '\n')
    wfile.close()

#將資料寫入Excel表
  def wExcel(self,infile,outEfile):
    rfile = open(infile,'r')
    buf = rfile.read().split('\n')
    rfile.close()

    w = xlwt.Workbook()
    sheet = w.add_sheet('sheet1')
    for i in range(len(buf)):
      print buf[i]
      sheet.write(i,0,buf[i].decode('utf8'))
    w.save(outEfile)

if __name__ == '__main__':
  t = OperExcel()
  t.rExcel('test.xls','test')
  t.wExcel('test','1.xls')

#encoding:utf8
import xlrd
import xlwt

class OperExcel():
  #讀取Excel表
  def rExcel(self,inEfile,outfile):
    rfile = xlrd.open_workbook(inEfile)
    #建立索引順序獲取一個工作表
    table = rfile.sheet_by_index(0)
    #其他方式
    #table = rfile.sheets()[0]
    #table = rfile.sheet_by_name(u'Sheet1')

    #獲取整行,整列的值
    table.row_values(0)
    table.col_values(0)

    #獲取行數和列數
    nrows = table.nrows - 1
    ncols = table.ncols

    #迴圈獲取列表的資料
    #for i in range(nrows):
    #  print table.row_values(i)
    wfile = open(outfile,'w')
    #獲取第一列中的所有值
    for i in range(nrows):
      #table.cell(i,0).value獲取某一單元格的值
      wfile.write(table.cell(i,0).value.encode('utf8') + '\n')
    wfile.close()

#將資料寫入Excel表
  def wExcel(self,outEfile):
    # rfile = open(infile,'r')
    # buf = rfile.read().split('\n')
    # rfile.close()
    buf = [ ['HK2815','其它','廣州','2015第117屆中國進出口商品交易會(2015年春季廣交會)紙書版會刊123期全套[預訂][包郵];','2015年04月15日 - 05月05日','廣州','琶洲會展中心','10000'],
            ['HK2809','美容美髮','上海','2014第21屆上海國際美容美髮化妝品博覽會;','2014年11月03日-11月05日','上海','光大會展中心','128']
          ]
    w = xlwt.Workbook()
    sheet = w.add_sheet('sheet1')
    for i in range(len(buf)):
      for j in  range(len(buf[i])):
      # print buf[i]
        sheet.write(i,j,buf[i][j].decode('utf8'))
    w.save(outEfile)

if __name__ == '__main__':
  t = OperExcel()
  #t.rExcel('test.xls','test')
  t.wExcel('test.xls')

然後就是程式碼的主程式了,細節問題請看主程式碼:

#-*- coding: UTF-8 -*-
import urllib
import urllib2
import requests
import re
import codecs
import xlwt

#作用就是將html檔案裡的一些標籤去掉,只保留文字部分
class HTML_Tool:
    BgnCharToNoneRex = re.compile("(\t|\n| |<a.*?>|<img.*?>)")
    EndCharToNoneRex = re.compile("<.*?>")
    BgnPartRex = re.compile("<p.*?>")
    CharToNewLineRex = re.compile("<br/>|</p>|<tr>|<div>|</div>")
    CharToNextTabRex = re.compile("<td>")

    def Replace_Char(self,x):
        x=self.BgnCharToNoneRex.sub("",x)
        x=self.BgnPartRex.sub("\n   ",x)
        x=self.CharToNewLineRex.sub("\n",x)
        x=self.CharToNextTabRex.sub("\t",x)
        x=self.EndCharToNoneRex.sub("",x)
        return x

#爬蟲類
class Spider:
    def __init__(self,parll,headerss,num):
        self.num = num+1
        self.par1 = parll
        self.headers = headerss
        self.s = requests.session()
        self.login = ""
        self.datas = []
        self.myTool = HTML_Tool()
        print u'會刊網爬蟲程式已啟動,正嘗試登陸...'

    def Solve(self):
        self.Login()
        self.get_data()
        # self.save_data(3)
        self.wExcel('huikan.xls')

    def wExcel(self, outEfile):
        w = xlwt.Workbook()
        sheet = w.add_sheet('sheet1')
        for i in range(len(self.datas)):
            for j in range(len(self.datas[i])):
                # print buf[i]
                sheet.write(i, j, self.datas[i][j].decode('utf8'))
        w.save(outEfile)
        print u'爬蟲報告:會刊目錄已儲存至當前資料夾下huikan.xls檔案'
        print u'載入完成,按任意鍵退出爬蟲程式'
        raw_input()
    # def save_data(self,endpage):
    #     f = codecs.open('huikan.xls','w+', "utf-8")
    #     for i in self.datas:
    #         str = u""
    #         for j in i:
    #             str=str+j.decode('utf-8')
    #         f.writelines(str+u'\n')
    #     f.close()
    #     print u'爬蟲報告:會刊目錄已儲存至當前資料夾下huikan.xls檔案'
    #     print u'載入完成,按任意鍵退出爬蟲程式'
    #     #raw_input()

    def Login(self):
        loginURL = "http://www.huikan.net/Login.asp?Action=Login"
        self.login = self.s.post(loginURL,data = self.par1,headers = self.headers)
        print u'爬蟲報告:模擬瀏覽器登陸成功,正在爬取資料...'

    def get_data(self):
        for i in range(1,self.num):
            print u'爬蟲報告:爬蟲%d號正在載入中...' %i
            afterURL = "http://www.huikan.net/allehuikan.asp?page="
            response = self.s.get(afterURL+str(i), cookies = self.login.cookies,headers = headers)
            mypage = response.content
            self.deal_data(mypage.decode('utf-8'))
            #print mypage

    def deal_data(self,mypage):
        myItems = re.findall('<tr>.*?<td height="30" class="tdcs" align="center" width="70">(.*?)</td>.*?<td height="30" class="tdcs" align="center" width="90">(.*?)</td>.*?<td height="9" align="center" class="tdcs" width="50">(.*?)</td>.*?<td height="9" class="tdcs">.*? (.*?)</a></td>.*?<td height="9" class="tdcs" width="170" align="center"> (.*?)</td>.*?<td height="9" align="center" class="tdcs" width="100">(.*?)</td>.*?<td height="9" class="tdcs" width="40" align="center">(.*?)</td>.*?</tr>',mypage,re.S)
        #print myItems
        for item in myItems:
            items = []
            #print item[0]+' '+item[1]+' '+item[2]+' '+item[3]+' '+item[4]+' '+item[5]+' '+item[6]
            items.append(item[0].replace("\n",""))
            items.append(item[1].replace("\n",""))
            items.append(item[2].replace("\n", ""))
            items.append(item[3].replace("\n", ""))
            items.append(item[4].replace("\n", ""))
            items.append(item[5].replace("\n", ""))
            items.append(item[6].replace("\n", ""))
            #print items
            mid = []
            for i in items:
                mid.append(self.myTool.Replace_Char(i.replace("\n","").encode('utf-8')))
            #print mid
            self.datas.append(mid)
        #print self.datas

#----------- 程式的入口處 -----------
print u"""
----------------------------------------------------------
   程式:網路爬蟲
   版本:V01
   作者:lvshubao
   日期:2016-04-11
   語言:Python 2.7
   功能:將會刊網中會刊目錄儲存到當前目錄下的huikan.xls表格
   操作:按任意鍵開始執行程式,載入時間可能會很長,請耐心等待
----------------------------------------------------------
"""
raw_input()
headers = {'Cache-Control': 'max-age=0','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8','Origin': ' http://www.huikan.net','Upgrade-Insecure-Requests': '1','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36','Accept-Language': 'zh-CN,zh;q=0.8','Cookie': 'pgv_pvi=7133927424; news=2014%u4E2D%u56FD%u56FD%u9645%u4FE1%u606F%u901A%u4FE1%u5C55%u89C8%u4F1A%A0%u7B2C1%u9875%204%u67083%u65E5%2012%3A52^http%3A//www.huikan.net/viphuikan.asp%3Fscck%3D1%26id%3D2588%26page%3D1$2014%u4E2D%u56FD%u56FD%u9645%u4FE1%u606F%u901A%u4FE1%u5C55%u89C8%u4F1A%A0%u7B2C1%u9875 4月3日 12:53^http%3A//www.huikan.net/viphuikan.asp%3Fscck%3D1%26id%3D2588%26page%3D1$|; ASPSESSIONIDSAQTDTSB=FHCEDBJAHJGPCOKONMNLEOGH; ASPSESSIONIDQATQARQC=DGKDMPABKDHMOHEAKJCLLJFB; pgv_si=s1220992000; PPst%5FLevel=3; PPst%5FUserName=handwudi; ehk%5Fname=handwudi; PPst%5FLastIP=222%2E171%2E12%2E123; PPst%5FLastTime=2016%2F4%2F10+18%3A27%3A38; visits=18; AJSTAT_ok_pages=2; AJSTAT_ok_times=4'}
data = {"Username":"123456","Passwrod":"123456","B1":"登陸"}
print u'請輸入爬蟲需要爬取的頁數:'
num = raw_input()
myspider = Spider(data,headers,int(num))
myspider.Solve()

tip:有些Python模組可能找不到,別忘了自己用pip install 去下載,另外推薦一個很全的網址:http://www.lfd.uci.edu/~gohlke/pythonlibs/

祝好運!


相關文章