文章目錄
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;">公佈內容: </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;">電子郵件: [email protected]</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;">地址:太原市長風商務區華潤大廈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;">電子郵件:[email protected]</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() # 獲取網頁純文本
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?
分析:相對導入只有在父模塊已經在當前運行環境中被導入過纔有用
解決:絕對路徑導入(簡單粗暴)