python爬虫(一):正则表达式爬取网页文本

1 正则表达式

修饰符描述
re.I使匹配对大小写不敏感
re.M多行匹配,影响 ^ 和 $
re.S使 . 匹配包括换行在内的所有字符
re.U根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解

2 网页文本爬取

最近在比比电子招投标交易平台浏览商机信息时发现,大部分的招标投信息都有相同的内容版块,但招投标内容格式又不尽相同。

2.1 单页文本

单页文本爬取可通过Beautiful Soup、Xpath和pyquery进行网页解析,从而避免使用正则表达式,以提高信息获取效率。

2.2 多页文本

多页文本爬取需要综合考虑不同页面布局和内容格式,此时选用正则表达式进行网页解析。

2.2.1 演示文本

(1)列表内容

 <tr>
    <td style="width:20%">
    	<span class="num">WBL2020-07(ZTSX[2020]0077)</span>
    <td style="width:40%">
    	<a target="_blank" title="2020年万柏林区下元街道办事处老旧小区改造项目第三标段(众纺路4号院、信息小区、土产小区)招标控制价" href="http://www.bitbid.cn:80/ggWeb/detailGG/zbgg.id_1050416_adType_secondLevelZbgg.html">【控制价】2020年万柏林区下元街道办事处老旧小区改造项目第三标段(众纺路4号院、信息小区、土产小区)招标控制价
		</a>
	</td>
    <td style="width:10%">工程</td>
    <td style="width:10%">山西省</td>

    <td style="width:10%">2020-05-13</td>
    <td style="width:10%">483</td>
</tr>

<tr>
    <td style="width:20%">
    	<span class="num">SXWC-2020-7034</span>
    <td style="width:40%">
    	<a target="_blank" title="大同煤矿集团大同煤炭运销黄土坡集运站有限公司环保煤棚重新招标招标公告" href="http://www.bitbid.cn:80/ggWeb/detailGG/zbgg.id_1050415_adType_secondLevelZbgg.html">大同煤矿集团大同煤炭运销黄土坡集运站有限公司环保煤棚重新招标招标公告
     	</a>
	</td>
    <td style="width:10%">工程</td>
    <td style="width:10%">山西省</td>
    <td style="width:10%">2020-05-13</td>
    <td style="width:10%">200</td>
</tr>

(2)文本内容

<div class="content">
	<h3>2020年万柏林区下元街道办事处老旧小区改造项目第三标段(众纺路4号院、信息小区、土产小区)招标控制价
	 <p class="sum" style="font-weight: normal">发布时间:2020-05-13 14:49:13 | 附件:无
	 </p>
	</h3>
	<div class="contentmain">
		<p style="text-align: center; font-size: 18px; text-decoration: underline;">2020年万柏林区下元街道办事处老旧小区改造项目第三标段(众纺路4号院、信息小区、土产小区)招标控制价</p><p style="text-align: center; font-size: 18px; text-decoration: underline;">(招标编号:WBL2020-07(ZTSX[2020]0077))</p><p><br/></p><p><span style="font-size: 16px; font-weight: bolder;">一、内容:</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">项目名称:2020年万柏林区下元街道办事处老旧小区改造项目第三标段(众纺路4号院、信息小区、土产小区)</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">招标编号:WBL2020-07(ZTSX[2020]0077)</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">公布内容:&nbsp;</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">1、招标控制价总价:10929518.46元,投标人投标总价不得超出招标控制价,否则其投标将被否决。</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">2、分部分项合计价:9470464.72元</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">3、措施项目合计价:265516.4元</span></p><p><span style="font-size: 16px; font-weight: bolder;">二、监督部门</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">本招标项目的监督部门为 太原市万柏林区发展和改革局 。</span></p><p><span style="font-size: 16px; font-weight: bolder;">三、联系方式</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;"></span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">招标人:太原市万柏林区住房和城乡建设局</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">地址:太原市万柏林区新晋祠路与汇锦街交叉口</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">联系人:武先生</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">联系电话:0351-6695795</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">电子邮件: 1009380373@qq.com</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">&nbsp;</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">招标代理机构:中通建设工程管理有限公司</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">地址:太原市长风商务区华润大厦T4-12层(长兴路1号)</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">联系人:李女士</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">电话:0351-7771113</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;">电子邮件:ztzb02@163.com</span></p><p style="text-indent: 2em;"><span style="line-height: 1.5em; font-size: 14px; font-weight: normal;"></span></p><p style="text-align: right; text-indent: 2em; font-size: 14px; font-weight: normal; margin-top: 150px;">招标人或其招标代理机构主要负责人(项目负责人):<span style="width: 120px; height: 20px; text-align: center; line-height: 20px; border-bottom-color: rgb(0, 0, 0); border-bottom-width: 1px; border-bottom-style: solid; display: inline-block;"></span> (盖章)</p><p><br/></p><p style="text-align: right; text-indent: 2em; font-size: 14px; font-weight: normal; margin-bottom: 0px;">招标人或其招标代理机构:<span style="width: 120px; height: 20px; text-align: center; line-height: 20px; border-bottom-color: rgb(0, 0, 0); border-bottom-width: 1px; border-bottom-style: solid; display: inline-block;"></span>(盖章)</p>
	</div>

2.2.2 文本信息获取

(1)列表详情——<tr></tr> & <td></td>

# 获取tr标签内容
records = re.findall('<tr>(.*?)</tr>', list, re.S|re.M)
# 获取第一个tr标签下的td内容
record = re.findall('<td>(.*?)</td>', records[0], re.S|re.M)

(2)超链接——<a href></a>

# 获取超链接a标签内容
label = re.findall('<a .*?>(.*?)</a>', record[1], re.S|re.M)[0]
# 获取href后url超链接地址
url = re.findall('(?<=href=\").*?(?=\")', record[1], re.S|re.M)[0]

(3)网页标题——<head></head> & <title></title>

# 从列表内容获取title
title = re.findall('(?<=title=\").*?(?=\")', record[1], re.S|re.M)[0]
# 从文本内容获取title
title = re.findall('(?<=<h3>).*?(?=<p)|<h3>(.*?)</h3>', content, re.S|re.M)[0]

(4)文本标签——<span></span>

# 从列表内容获取项目编号
code = re.findall('<span .*?>(.*?)</span>', record[0], re.S|re.M)[0]
# 从文本内容获取项目编号
code = re.findall('(?<=招标编号:).*?(?=<)', content, re.S|re.M)[0]

3 实战记录

3.1 网页纯文本处理

3.1.1 常规网页

response = requests.get(url=url, headers=header) # 获取网页内容
# print(response.encoding) # ISO-8859-1
response = (response.text).encode('ISO-8859-1').decode('UTF-8') # 网页重编码
#----------------------------------------------# 
content = BeautifulSoup(response, 'lxml').get_text() # 获取网页纯文本
#----------------------------------------------# 
text = re.sub('\s','',content) # 去掉换行等因素造成的文本空格(可选,有时不去掉空格更有利于获取文本内容)

3.1.2 隐藏域

response = requests.get(url=url, headers=header) # 获取网页内容
# print(response.encoding) # ISO-8859-1
response = (response.text).encode('ISO-8859-1').decode('UTF-8') # 网页重编码
#----------------------------------------------# 
# 提取隐藏域信息
response = re.findall('(?<=<input type="hidden").*?(?=>)', response, re.S | re.M)
response = ''.join(response)
# 直接选择lxml会消除隐藏域,需搭配两种解析器使用
content = BeautifulSoup(response, 'html.parser').get_text()
content = BeautifulSoup(content, 'lxml').get_text()

3.2 数据存储

3.2.1 csv文件

'''
csv_path:csv文件读写路径
list1, list2:写入信息(列表)
'''
def info_to_csv(csv_path, list1, list2):
    with open(csv_path, 'a', newline='', encoding='utf-8') as f:
    	f.write("{}, {}".format(list1, list2))
    	f.close()

'''
补充内容:将csv转为excel(若爬取网页文本,请慎用)
'''
import csv
def csv_to_excel_pd(csv_path, excel_path):
    csv = pd.read_csv(csv_path, encoding='utf-8', error_bad_lines=False, delimiter=',')
    # print(csv)
    csv.to_excel(excel_path, sheet_name = '文本信息')

3.2.2 excel文件

'''
excel_path:excel文件读写路径
list1, list2:写入信息(列表)
df:写入信息(数据框)
'''
import pandas as pd
# 将爬取的数据以追加的方式保存到本地excel文件
df = pd.DataFrame()
df['01'] = list1
df['02'] = list2
def info_to_excel(excel_path, df):
	writer = pd.ExcelWriter(excel_path)
	df.to_excel(writer, sheet_name='文本信息', index=False)
    writer.save()
    writer.close()

4 问题记录

(1)pd.read_csv() 提示 OSError: Initializing from file failed?
分析:中文路径影响
解决:指定enginepd.read_csv('path',engine='python')或借助open函数pd.read_csv(open('path'))

(2)网页乱码如何解决?
分析:查看网页编码requests(url).encoding()
解决:重新编码解码requests(url).text.encode('ISO-8859-1').decode('utf-8')

(3)相对导入当前目录下其它py文件提示:ModuleNotFoundError: No module named ‘main.xxxx’; ‘main’ is not a package?
分析:相对导入只有在父模块已经在当前运行环境中被导入过才有用
解决:绝对路径导入(简单粗暴)

(4)requests.exceptions.ConnectTimeout: HTTPConnectionPool(host=‘xxxx’, port=80): Max retries exceeded with url: ?
分析:requests连接超时,服务器在指定时间没有应答,导致的原因包括url连接过多未关闭访问过度频繁
解决:在不使用ip代理的情况下,可参考以下两种方法:
① 连接过多未关闭

requests.adapters.DEFAULT_RETRIES = 5 # 增加重连次数
rs = requests.session()
rs.keep_alive = False # 关闭多余连接

② 访问过度频繁

time.sleep()
  • 3
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值