Request爬取各類網站的數據(實例爬取)


1. 先上代碼

 1 # !/usr/bin/env python
 2 # ! _*_ coding:utf-8 _*_
 3 # @TIME : 2020/10/12 13:29
 4 # @Author : Noob
 5 # @File : bases.py
 6 
 7 import requests  8 from bs4 import BeautifulSoup  9 import re  10 import xlwt  11 import xlrd  12 
 13 class Bases:  14 
 15     fo = open('data.txt', 'r', encoding='utf-8')  16     lines = fo.readlines()  17 
 18     # 說明書讀取
 19     def readExplain(self):  20 
 21         x = input("是否讀取說明(y or n):")  22         if x == 'y':  23             ro = open('explain.txt', 'r+', encoding='utf-8')  24             strs = ro.read()  25             print(strs)  26  ro.close()  27         else:  28             pass
 29 
 30     # 動態url
 31     def getUrl(self, keywords, starts):  32 
 33         lines = self.lines  34         baseurl = lines[15].strip()  35         key = lines[17].strip()  36         fw = lines[23].strip()  37         bw = lines[25].strip()  38 
 39         if '.' in fw or bw:  40             fwf = fw.replace('.', '\.')  41             bwf = bw.replace('.', '\.')  42         else:  43             fwf = fw  44             bwf = bw  45         if fw != '':  46             url = re.sub(fwf + '(.+?)' + bwf, fw + str(starts) + bw, baseurl)  47             url = url.replace(key, keywords)  48         else:  49             url = baseurl.replace(key, keywords)  50         if '$' in url:  51             url = url[0: -1]  52         print('當前url是:%s' % url)  53         return url  54 
 55     # 請求頭
 56     def getHeader(self):  57 
 58         lines = self.lines  59         header = {  60             'accept': lines[5].strip(),  61             'accept-encoding': lines[7].strip(),  62             'accept-language': lines[9].strip(),  63             'cache-control': lines[11].strip(),  64             'Connection': lines[13].strip(),  65             'Upgrade-Insecure-Requests': lines[3].strip(),  66             'User-Agent': lines[1].strip()  67  }  68         return header  69 
 70     # 封裝請求
 71     def getContent(self, key='學霸', start=0):  72 
 73         url = self.getUrl(key, start)  74         try:  75             assert ('http' in url)  76         except:  77             return 'url有問題,請重來!!!'
 78         else:  79             res = requests.get(url, headers=self.getHeader())  80             if res.status_code == 200:  81                     return res  82             else:  83                 return '請求失敗,狀態碼為:%d' % res.status_code, 'error'
 84         finally:  85             # print('這是一個檢查url是否正確的塊')
 86             pass
 87 
 88     # 獲取完整文本
 89     def getContents(self, key):  90 
 91         lines = self.lines  92         try:  93             offset = int(lines[19])  94             j = int(lines[21].strip())  95         except ValueError as msg:  96             print('輸入數據有錯,請返回檢查!!!', msg)  97         else:  98             words = lines[27].strip()  99             resText = ''
100             while 1: 101                 res = self.getContent(key, j) 102 
103                 res.encoding = 'utf-8'  # 中文亂碼的時候
104 
105                 if type(res) == str: 106                     print(res) 107                     break
108                 if type(res) == tuple: 109                     print(res) 110                     break
111                 if res.status_code == 400: 112                     break
113                 if len(res.text) < 100: 114                     break
115                 if words not in res.text: 116                     break
117                 if str(j) not in res.url:  # 當沒有頁碼或者滑動加載的時候,並不准確
118                     resText = resText + res.text 119                     break
120                 resText = resText + res.text 121                 j = j + offset 122             resText = resText.replace('<!DOCTYPE html>', '') 123             resText = BeautifulSoup(resText, features='html.parser') 124             eo = open('export.txt', 'w', encoding='utf-8') 125  eo.write(str(resText)) 126  eo.close() 127             return resText 128 
129     # 數據過濾
130     def getFilter(self, key): 131 
132         lines = self.lines 133         resText = str(self.getContents(key)) 134 
135         counts = int(lines[29].strip()) 136 
137         j = 31  # 匹配規則開始下標
138         datas = []  # 所有匹配數據列表名
139 
140         for i in range(counts): 141             pattern = lines[j].strip() 142  datas.append(re.compile(pattern).findall(resText)) 143             j = j + 2
144 
145         # 數據爬取到TXT
146         # ao = open('abc.txt', 'a', encoding='utf-8')
147         # 148         # ao.write(ns[0] + '\t' + ns[1] + '\t' + ns[2] + '\t' + ns[3] + '\n') # 項目名制成表頭
149         # 150         # for i in range(len(datas[0])):
151         # k = ''
152         # for j in range(len(datas)):
153         # k = k + datas[j][i] + '\t'
154         # ao.write(k + '\n')
155         # ao.close()
156         return datas 157 
158 
159     # 從Excel中讀取搜索數據
160     def readExcel(self): 161 
162         xd = xlrd.open_workbook('ok.xlsx') 163         sn = xd.sheet_by_index(0) 164         coms = [] 165         j = 1
166         while 1: 167             com = sn.cell_value(j, 0) 168             if com == '': 169                 break
170  coms.append(com) 171             j = j + 1
172         return coms 173 
174     # 數據寫到Excel
175     def writeExcel(self): 176 
177         data = self.readExcel()  # 二維數組
178         datas = []  # 三維數組datas[a][b][c]
179         for i in range(len(data)): 180             data[i] = self.getFilter(data[i]) 181  datas.append(data[i]) 182 
183         print(datas) 184 
185         # 創建表
186         xt = xlwt.Workbook(encoding='gbk') 187         sn = xt.add_sheet('what') 188 
189         # 制表頭
190         lines = self.lines 191         # 找到匹配開始的元素索引和項目名
192         j = 0 193         for i in lines: 194             if '正則匹配規則' in i: 195                 n = re.compile(r'#(.+?)#').findall(i.strip()) 196                 if len(n) > 0: 197                     sn.write(0, j, n[0])  # 第幾行第幾列值是什么
198                     j = j + 1
199 
200             # 單元格寬度:0的占位符是256,那么20個0就是256*20
201             if '單元格寬度' in i: 202                 i = lines[lines.index(i) + 1] 203                 i = i.split('*')  # 字符串切割成數組
204                 for k in range(len(i)): 205                     sn.col(k).width = 256*int(i[k]) 206 
207         # 寫入數據
208         count = 1  # 計行
209         for i in datas: 210             for j in range(len(i[0])):  # 每個搜索值的數量
211                 for k in range(len(i)): # 搜索項數量
212                     sn.write(count, k, i[k][j])  # 這里不要寫錯了
213                 count = count + 1
214 
215         return xt.save('ok.xls')  # 保存格式必須是.xls,否則失敗
216 
217     # 運行
218     def main(self): 219         print('運行開始abc') 220  self.writeExcel() 221 
222  fo.close() 223 
224 if __name__ == '__main__': 225     bs = Bases() 226     bs.main()
bases.py

2. 網站及其搜索項在這個txt中配置(后面有一個explain的文檔有詳細說明)

 1 ----請輸入User-Agent:
 2 Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4098.3 Safari/537.36
 3 ----請輸入Upgrade-Insecure-Requests:
 4 1
 5 ----請輸入accept:
 6 text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
 7 ----請輸入accept-encoding:
 8 gzip, deflate, br
 9 ----請輸入accept-language:
10 zh-CN,zh;q=0.8
11 ----請輸入cache-control:
12 max-age=0
13 ----請輸入Connection:
14 keep-alive
15 ----請輸入搜索一個數據后的完整網址:
16 http://www.biquku.la/modules/article/search.php?searchkey=%E5%AD%A6%E9%9C%B8
17 ----請輸入網址中的關鍵詞:
18 %E5%AD%A6%E9%9C%B8
19 ----請輸入頁碼差或滑動偏移量(沒有就填0):
20 0
21 ----請輸入默認開始頁數或者第一條數據(沒有就填0):
22 0
23 ----請輸入偏移量前面的字符(沒有頁碼就不填):
24 
25 ----請輸入偏移量后面的字符(沒有頁碼不填,如果有頁碼,但是頁碼后面沒有字符輸入$):
26 
27 ----請輸入需要中斷請求的連續字符(可以為空,也有可能導致死循環,比如前程無憂,會無限發送請求,根據網站來):
28 
29 ----請輸入匹配項目數量
30 4
31 ----請輸入第一條要輸出內容#文章名稱#的正則匹配規則
32 /\" target=\"_blank\">(.+?)</a>
33 ----請輸入第二條要輸出內容#最新章節#的正則匹配規則
34 \.html\" target=\"_blank\">(.+?)</a></span>
35 ----請輸入第三條要輸出內容#作者#的正則匹配規則
36 <td class=\"nowrap\">(.+?)</td>
37 ----請輸入第四條要輸出內容#更新日期#的正則匹配規則
38 <td>(.+?)</td>
39 ----請輸入第五條要輸出內容##的正則匹配規則
40 
41 ----請輸入單元格寬度(大概字符個數):
42 30*30*20*20
data.txt

 

3. 關鍵字數據寫在Excel中:ok.xlsx

4. 輸出的有三個文本

  --export.txt:輸出整個文檔,方便寫正則規則

  --ok.xls:輸出爬取的數據

  --abc.txt:輸出爬取數據,代碼被注釋了,看自己需要

 5. 解釋data.txt的填寫

 1 ----------------------------------------------------------------------------------------------
 2 ----------------------------------------------------------------------------------------------
 3  在data.txt中修改數據進行網頁爬取  4         1. 當沒有頁碼或偏移量的時候,19-28行問題可忽略不寫  5         2. 匹配項目數量這個要寫,這里寫多少,下面就填多少個匹配規則  6         3. 匹配項目前的問題不要改動位置,有些地方索引寫死了,有需要再改代碼  7         4. 請求中斷連續字符,即發送的請求返回的文本中不存在的內容  8             --在前程無憂中,如果不輸入中斷字符,會無線循環,不包含搜索數據也會繼續下去  9             --在前程無憂我選擇company_name作為中斷字符串,包含搜索數據的會請求,不包含的就中斷 10 ----------------------------------------------------------------------------------------------
11 ----------------------------------------------------------------------------------------------
12  判斷偏移量和頁數的問題的方式 13         1. 頁碼:先翻頁,查看兩次鏈接有什么不同的地方 14         2. 滑動加載:打開network,滑動加載頁面,在這里取鏈接,查看一次加載的變動數據量 15         3. 翻頁offset:一般相差1 16         4. 滑動offset:滑動后的數值減去滑動前的數值 17             --比如領英的滑動前的start=0,滑動后start=25,那么offset=25
18 ----------------------------------------------------------------------------------------------
19 ----------------------------------------------------------------------------------------------
20  注意問題: 21         1. fw和bw的符號為英文格式 22         2. offset后面如果沒有字符,bw輸入英文的$ 23         3. fw和bw的值需兩個字符以上,盡可能長的不會和其他字符或串有重復 24 ----------------------------------------------------------------------------------------------
25 ----------------------------------------------------------------------------------------------
26  使用方式:舉例子 27         1. 前程無憂 28             --完整網址:https://search.51job.com/list/000000,000000,0000,00,9,99,%25E8%2595%25BE%25E4%25B8%259D,1,1.html 29             --關鍵字:%25E8%2595%25BE%25E4%25B8%259D 30             --偏移量:1
31             --起始頁:1
32             --頁碼或偏移數前的字符:,1, 33             --頁碼或偏移數前的字符:.html 34         2. 領英 35             --完整網址:https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?keywords=%E8%A5%BF%E9%97%A8%E5%AD%90&location=%E4%B8%AD%E5%9B%BD&geoId=&trk=public_jobs_jobs-search-bar_search-submit&start=25
36             --關鍵字:%E8%A5%BF%E9%97%A8%E5%AD%90
37             --偏移量:25
38             --起始數:0 39             --頁碼或偏移數前的字符:rt=
40             --頁碼或偏移數后的字符:$ 41         3. 筆趣閣 42             --http://www.biquku.la/modules/article/search.php?searchkey=%E5%AD%A6%E9%9C%B8 43             --%E5%AD%A6%E9%9C%B8 44             --沒有偏移量,填0 45             --起始數據不存在:填0 46             --不填 47             --不填 48 ----------------------------------------------------------------------------------------------
49 ----------------------------------------------------------------------------------------------
explain.txt

6. 用到的知識點(沒寫全)

 1 -----------------------------------------------------------
 2                     知識點
 3 -----------------------------------------------------------
 4 # 網頁數據爬取
 5 #   1. request庫
 6 #   2. bs4 > BeautifulSoup庫
 7 #   3. 寫到數據篩選的時候發現有些網站不適合用bs4,比如前程無憂,所以這里使用re庫
 8 # 多線程
 9 #   1.
10 # 數據讀取Excel(看需要,自己寫着玩的話,我更喜歡TXT,沒得選的話,還有其他各種各樣的文件格式有的學)
11 #   1. xlrd庫
12 # 數據寫入Excel
13 #   1. xlwt庫
14 #   2. 相關知識鏈接:https://www.cnblogs.com/zhangyang123/p/10784741.html
15 #   3. 使用這個庫不能進行數據追加修改,每次都覆蓋,想要修改追加的話再使用庫xlutils
16 #   4. 相關知識鏈接:https://blog.csdn.net/u013250071/article/details/81911434
17 # txt讀取寫入
18 #   1. 打開文件:fo = open(filename.txt, mode, encoding)
19 #   2. 讀整個文件:fo.read()
20 #   3. 按字符讀:fo.read(counts)
21 #   4. 按行讀:fo.readlines() ==> 這是一個數組,每一行是一個元素
22 #   5. 去行末尾的隱藏\n:line.strip()
23 #   6. 注意模式mode,如果是追加寫入mode用a,如果覆蓋寫入用w或w+
24 #   7. 相關知識鏈接:https://www.cnblogs.com/xuxn/archive/2011/07/27/read-a-file-with-python.html
25 # 變量動態命名
26 #   1. 這里要注意是全局還是局部的命名:exec和locals是全局的,globals是局部的
27 #   2. 調用變量的方式也可以學一學,本來打算用這個命名方式的,后來發現不用也行
28 #   3. 相關知識鏈接:https://www.runoob.com/w3cnote/python-dynamic-var.html
Readme.txt

——以后有空再修改代碼做成有界面的形式,txt填寫數據不是很方便,只進行小范圍的測試


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM