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()
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
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 ----------------------------------------------------------------------------------------------
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
——以后有空再修改代碼做成有界面的形式,txt填寫數據不是很方便,只進行小范圍的測試