当前位置:
首页 > temp > python入门教程 >
-
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()
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填写数据不是很方便,只进行小范围的测试
出处:https://www.cnblogs.com/noobzeng/p/13811365.html
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程
检测数据类型的四种方法
js中数组的方法,32种方法
前端操作方法
数据类型
window.localStorage.setItem 和 localStorage.setIte
如何完美解决前端数字计算精度丢失与数