クローラーの実践: 陝西省入札クローラー (3 つの Web サイト) xpath パッケージと exe

最近、クローラーを依頼されたのですが、初期段階での連絡ミスにより、何度か手戻りが発生してしまいました。(まだ手直し中)

ようやく成功し、パッケージ化されたコードプロジェクトを作成し、実行します

exeはこんな感じ

クリックすると、図に示すように、tkinter によって記述されたインターフェイスを取得できます。

クリックするとデスクトップに表示されます。

 早速ですが、カタログは以下の通りです。

目次

完全なコード

ライブラリリファレンス

デフタイム関数

対象Webサイトのリンク生成をクロールします

対象Webサイトのクローリング機能

tkinter 部分

ボックスを設定する関数

ボタンを設定する機能

背景テキストを設定するための追加機能

そして、tkinter の終了後に忘れずに記述するコード行 (非常に重要)

パッケージ化exeチュートリアルについて

使用したexeツール

exeの仮想環境を作成する

 すべての仮想環境を表示するには

 仮想環境の構成

パッケージングパスの表示

パッケージ実行コマンド

ロゴを美しくする

結果


完全なコード


import requests
import json
import pandas as pd
import time
import requests # python基础爬虫库
from lxml import etree # 可以将网页转换为
import datetime
import tkinter as tk
import openpyxl

#爬虫代做+v:j1yzbzjpzyxz
#时间函数

def getdate(self,beforeOfDay):
    today = datetime.datetime.now()
    # 计算偏移量
    offset = datetime.timedelta(days=-beforeOfDay)
    # 获取想要的日期的时间
    re_date = (today + offset).strftime('%Y-%m-%d')
    return re_date




#zgzf采购网网页生成函数
def getSearchlist():
    search_list=['#你想在该网站搜索的关键词']
    url_list=[]
    for i in range(len(search_list)):
        for o in range(3):
            a=o+1
            url_list=url_list+["https://search.ccgp.gov.cn/bxsearch?searchtype=2&page_index="+str(a)+"&bidSort=&buyerName=&projectId=&pinMu=&bidType=&dbselect=bidx&kw="+search_list[i]+"&start_time="+getdate(0,3)+"&end_time="+str(datetime.datetime.now().strftime('%Y-%m-%d'))+"&timeType=2&displayZone=陕西&zoneId=&pppStatus=0&agentName="]
    return url_list


#zgzf采购网网页爬取函数
def ccgp():
    web_list=[]
    region_list=[]
    time_list=[]
    dady_list=[]
    title_list=[]
    header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36'}
    for p in range(len(getSearchlist())):
        time.sleep(6)
        url2 =getSearchlist()[p]
        response2 = requests.get(url= url2,headers=header) 
        response2.encoding = 'utf-8'
        wb_data2 = response2.text
        html = etree.HTML(wb_data2) 
        www=html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li/a/@href')
        for i in range(len(www)):
            i=i+1
            web_list=web_list+html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/a/@href')
       
    
            title_list=title_list+[str(html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/a[@href]/text()')).split("\\r\\n                                        ")[1].split("\\r\\n")[0]]
            
        
            time_list=time_list+[str(html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/span/text()[1]')).split("['")[1].split(" ")[0]]
                             

            dady_list=dady_list+[str(html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/span/text()[1]')).split("|")[1].split("\\r\\n ")[0]]
        

        
            ww=html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/span/a/text()')
            if ww==[]:
                region_list=region_list+['None']
            else:
                region_list=region_list+html.xpath('//div/div/div[1]/ul/li['+str(i)+']/span/a[@href="javascript:void(0)"]/text()')
            
            i=i-1
            
            
            
    a=pd.DataFrame({'标题':title_list,'地区':region_list,'时间':time_list,'采购人':dady_list,'详细网址':web_list})
    
    a=a[a['地区']=='陕西']

    a.to_excel(excel_writer = r"F:\\desktop\\导出结果(爬虫中国政府采购网).xlsx")
    return a



#陕西省政府采购网
def get_ccgpshaanxi_Searchlist():
    search_list=['#你想在该网站搜索的关键词']
    url_list=[]
    for i in range(len(search_list)):
        url_list=url_list+["http://www.ccgp-shaanxi.gov.cn/freecms/rest/v1/notice/selectInfoMoreChannel.do?&siteId=a7a15d60-de5b-42f2-b35a-7e3efc34e54f&channel=&title=&content="+search_list[i]+"&regionCode=&noticeType=&operationStartTime="+getdate(0,1)+"%2000:00:00&operationEndTime="+str(datetime.datetime.now().strftime('%Y-%m-%d'))+"%2023:59:59&currPage=1&pageSize=10&cityOrArea="]
    return url_list

def ccgpshaanxi():
    title=[]
    dady=[]
    agency=[]
    web=[]
    reigon=[]
    budget=[]
    issue_time=[]
    notice=[]
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36'}
    for p in range(len(get_ccgpshaanxi_Searchlist())):
        url2 =get_ccgpshaanxi_Searchlist()[p]
        response2 = requests.get(url= url2,headers=headers)
        response2 .encoding = 'utf-8'
        wb_data_2 = response2.text
        html = etree.HTML(wb_data_2)
        for i in range(len(json.loads(wb_data_2)['data'])):
            title=title+[json.loads(wb_data_2)['data'][i]['title']]
            web=web+["http://www.ccgp-shaanxi.gov.cn/freecms"+json.loads(wb_data_2)['data'][i]['htmlpath']]
            reigon=reigon+[json.loads(wb_data_2)['data'][i]['regionName']]
            issue_time=issue_time+[json.loads(wb_data_2)['data'][i]['openTenderTime']]
            notice=notice+[json.loads(wb_data_2)['data'][i]['noticeTime']]
            budget=budget+[str(json.loads(wb_data_2)['data'][i]['budget'])]
            dady=dady+[str(json.loads(wb_data_2)['data'][i]['purchaser'])]
    a=pd.DataFrame({'标题':title,'发布时间':issue_time,'notice':notice,'预算(元)':budget,'发布地区':reigon,'详细网址1':web,'甲方':dady})
    a.to_excel(excel_writer=r"F:\\desktop\\导出结果(陕西省政府采购网).xlsx")
    return a



#陕西省招投标平台
def get_bulletin_Searchlist():
    search_list=['#你想在该网站搜索的关键词']
    url_list=[]
    for i in range(len(search_list)):
        url_list=url_list+["http://bulletin.sntba.com/xxfbcmses/search/bulletin.html?searchDate="+getdate(0,2)+"&dates=2&categoryId=88&industryName=&area=&status=&publishMedia=&sourceInfo=&showStatus=&word="+str(search_list[i])]
        return url_list

def bulletin():
    title=[]
    web=[]
    reigon=[]
    issue_time=[]
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36'}
    for x in range(len(get_bulletin_Searchlist())):
        response3 = requests.get(url=get_bulletin_Searchlist()[x],headers=headers)
        time.sleep(6)
        wb_data3 = response3.text
        html = etree.HTML(wb_data3)
        jishu=html.xpath('//table//tr/td/a/text()')
        for i in range(len(jishu)):
            i=i+2
            title=title+[str(html.xpath('//table//tr['+str(i)+']/td/a/text()')).split('t')[6].split('\r')[0]]
            web=web+[str(html.xpath('//table//tr['+str(i)+']/td/a/@href')).split("'")[1]]
            reigon=reigon+[str(html.xpath('//table//tr['+ str(i) +']/td[3]/span/text()')).split('t')[6].split('\r')[0]]
            issue_time=issue_time+[str(html.xpath('//table//tr   ['+ str(i) +']/td[5]/text()')).split('t')[6].split('\r')[0]]
            i=i-2
    a=pd.DataFrame({'标题':title,'原网址':web,'发布时间':issue_time,'发布地区':reigon})
    a.to_excel(excel_writer = r"F:\\desktop\\导出结果(陕西省招标投标公共服务平台).xlsx")
    return a






#设计按钮
from tkinter import *
root= tk.Tk()
root.title('爬虫招标信息采集——中国陕西')
root.geometry('400x240') # 这里的乘号不是 * ,而是小写英文字母 x


btn1 = Button(root,text="中国政府采购网",command=ccgp())
btn1.place(relx=0.2,rely=0.4, relwidth=0.3, relheight=0.1)
btn1.pack()

btn2 = Button(root,text="陕西省政府采购网",command=ccgpshaanxi())
btn2.place(relx=0.4,rely=0.4, relwidth=0.6,relheight=0.1)
btn2.pack()

btn3 = Button(root,text="陕西省招标投标公共服务平台",command=bulletin())
btn3.place(relx=0.6,rely=0.4, relwidth=0.9,relheight=0.1)
btn3.pack()


theLabel = tk.Label(root,text="点击按钮获得今日招投标信息",justify=tk.LEFT,compound = tk.CENTER,font=("华文行楷",20),fg = "grey")
theLabel.pack()


root.mainloop()


# In[ ]:




以下はコード解析です。

まず、ライブラリのリファレンスセクション

ライブラリリファレンス

import json
import pandas as pd
import time
import requests # python基础爬虫库
from lxml import etree # 可以将网页转换为
import datetime
import tkinter as tk
import openpyxl

私は Xpath の方が慣れているので、このクローラー プロジェクトも Xpath を使用して作成しています。

特に一番下のopenpyxlライブラリは参考範囲外だったのですが、関数をカプセル化した後にexeがエラーを報告し、エラーメッセージによるとopenpyxlライブラリが見つからなかったのでpipインストールしてインポートしたところエラーは解決しました。

デフタイム関数


#时间函数

def getdate(self,beforeOfDay):
    today = datetime.datetime.now()
    # 计算偏移量
    offset = datetime.timedelta(days=-beforeOfDay)
    # 获取想要的日期的时间
    re_date = (today + offset).strftime('%Y-%m-%d')
    return re_date

 今回の機能は超便利!

多くの入札 Web サイトには、時刻を含む情報が Web サイトに保存されているためです。

例えば

調達公告検索_中国政府調達ネットワーク

 (Webサイトはこんな感じです)

http://search.ccgp.gov.cn/bxsearch?searchtype=2&page_index=1&bidSort=0&buyerName=&projectId=&pinMu=0&bidType=0&dbselect=bidx&kw=%E7%9A%84&start_time=2022%3A07%3A02&end_time=2022%3A08%3A02&timeType=3&displayZone=&zoneId=&pppStatus=0&agentName=

この Web サイトへのリンクには ----- start_time=2022%3A07%3A02&end_time=2022%3A08%3A02 が含まれています

URL内の日時の表現です

get date関数は計算することです

現在の日付から数日繰り上げた日付

例: getdate(,2) と入力します。

今日の日付の2日前の日付を取得できます

詳細な使用法については、中国政府調達ネットワークのクローラー リストを生成するコードを参照してください。

対象Webサイトのリンク生成をクロールします

def getSearchlist():
    search_list=['#你想在该网站搜索的关键词']
    url_list=[]
    for i in range(len(search_list)):
        for o in range(3):
            a=o+1
            url_list=url_list+["https://search.ccgp.gov.cn/bxsearch?searchtype=2&page_index="+str(a)+"&bidSort=&buyerName=&projectId=&pinMu=&bidType=&dbselect=bidx&kw="+search_list[i]+"&start_time="+getdate(0,3)+"&end_time="+str(datetime.datetime.now().strftime('%Y-%m-%d'))+"&timeType=2&displayZone=陕西&zoneId=&pppStatus=0&agentName="]#自行解析的网站链接
    return url_list

図のようにキーワードを入力すると、その日の情報が掲載されているWebサイトのURLが取得されます。

対象Webサイトのクローリング機能

def ccgp():
    web_list=[]
    region_list=[]
    time_list=[]
    dady_list=[]
    title_list=[]
###建立爬取字段
    header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36'}
###设置当前爬取请求头
    for p in range(len(getSearchlist())):
        time.sleep(6)###这个网站请求过快会被屏蔽,所以使用time.sleep(6)暂停六秒再进行请求
        url2 =getSearchlist()[p]###依次遍历前面getSearchlist()中包含的网站
        response2 = requests.get(url= url2,headers=header) ###开始请求
        response2.encoding = 'utf-8'
        wb_data2 = response2.text
        html = etree.HTML(wb_data2) 
        www=html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li/a/@href')###获取该页有多少条信息需要爬取
        for i in range(len(www)):###根据需要信息条数进行遍历
            i=i+1
###开始爬取      web_list=web_list+html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/a/@href')
       
    
            title_list=title_list+[str(html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/a[@href]/text()')).split("\\r\\n                                        ")[1].split("\\r\\n")[0]]
            
        
            time_list=time_list+[str(html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/span/text()[1]')).split("['")[1].split(" ")[0]]
                             

            dady_list=dady_list+[str(html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/span/text()[1]')).split("|")[1].split("\\r\\n ")[0]]
        

        
            ww=html.xpath('//div[5]/div[2]/div/div/div[1]/ul/li['+str(i)+']/span/a/text()')
            if ww==[]:
                region_list=region_list+['None']
            else:
                region_list=region_list+html.xpath('//div/div/div[1]/ul/li['+str(i)+']/span/a[@href="javascript:void(0)"]/text()')
            
            i=i-1
            
            
            
    a=pd.DataFrame({'标题':title_list,'地区':region_list,'时间':time_list,'采购人':dady_list,'详细网址':web_list})
###筛选爬取地区
    a=a[a['地区']=='陕西']
###导出为excel
    a.to_excel(excel_writer = r"F:\\desktop\\导出结果(爬虫中国政府采购网).xlsx")
    return a

他の 2 つの Web サイトのクローリングは、基本的に中国政府調達ネットワークのクローリングと同様です。

tkinter 部分

#设计按钮
from tkinter import *
root= tk.Tk()
root.title('爬虫招标信息采集')
root.geometry('400x240') # 这里的乘号不是 * ,而是小写英文字母 x


btn1 = Button(root,text="1号采购网",command=ccgp())
btn1.place(relx=0.2,rely=0.4, relwidth=0.3, relheight=0.1)
btn1.pack()

btn2 = Button(root,text="2号采购网",command=ccgpshaanxi())
btn2.place(relx=0.4,rely=0.4, relwidth=0.6,relheight=0.1)
btn2.pack()

btn3 = Button(root,text="3号招标投标公共服务平台",command=bulletin())
btn3.place(relx=0.6,rely=0.4, relwidth=0.9,relheight=0.1)
btn3.pack()


theLabel = tk.Label(root,text="点击按钮获得今日招投标信息",justify=tk.LEFT,compound = tk.CENTER,font=("华文行楷",20),fg = "grey")
theLabel.pack()


root.mainloop()

tkinter 部分は実際には非常に単純で、プログラム ボックスを記述し、ボックス内に 3 つのボタンを配置し、クリックすると対応する Web サイトの機能をトリガーします。

ボックスを設定する関数

root= tk.Tk()
root.title('爬虫招标信息采集——中国陕西')
root.geometry('400x240') # 这里的乘号不是 * ,而是小写英文字母 x

ボタンを設定する機能

btn1 = Button(root,text="中国政府采购网",command=ccgp()#触发函数写在这里)
btn1.place(relx=0.2,rely=0.4, relwidth=0.3, relheight=0.1)
btn1.pack()

背景テキストを設定するための追加機能

theLabel = tk.Label(root,text="点击按钮获得今日招投标信息",justify=tk.LEFT,compound = tk.CENTER,font=("华文行楷",20),fg = "grey")
theLabel.pack()

そして、tkinter の終了後に忘れずに記述するコード行 (非常に重要)

root.mainloop()

最終的なプログラムはこんな感じ

 上記の作業がすべて完了し、機能が正常であることを確認したら、すべての機能を 1 つのプロジェクトに統合し、.py 形式で保存します。

写真が示すように

.py ファイルは、pycharm では次のようになります。 

パッケージ化exeチュートリアルについて

使用したexeツール

まず、anaconda シリーズの Python コンパイラー (非常に使いやすく、暴力的な怒りによって推奨されています) を使用し、anaconda プロンプトを使用します。

写真の通り、こんな物です

 クリックすると、以下を取得できます。

 小さな黒い箱

この小さなブラック ボックスは、exe の操作とパッケージ化の焦点です。このプロジェクトでは、exe の仮想環境を使用します。

exeの仮想環境を作成する

まず、小さな黒いボックスに入力します

conda -n XXX(你想起的虚拟环境名字) python=XXX(你想用的python版本编号例如:XXX可以写为3.6)
如果不指定版本
只写
conda -n XXX(你想起的虚拟环境名字)
就好

作成プロセス中に「はい」と応答して (y/n)、仮想環境をアクティブ化する必要があります。

アクティベーションの前に:

 アクティベーション後:

condaでインストールした仮想環境は、anacondaのインストールディレクトリ配下のenvディレクトリに仮想環境のディレクトリが生成されますので、前に作成した仮想環境を探したい場合はこのディレクトリ内を検索するか、ブラックボックスに入力してください

conda info --envs

 すべての仮想環境を表示するには

 上記では、必要な仮想環境を作成してアクティブ化しました。作成後、conda list現在の仮想環境にインストールされているライブラリを表示できます。

表示後、図に示すように:

 仮想環境の構成

仮想環境にカプセル化したいpyファイルでインポートしたライブラリが存在しないことが判明した場合

これは、次のように仮想環境で pip を実行することで解決できます。

pip install xxx(库名)
解决问题

本次爬虫需要pip的库为
pip install requests
pip install pandas
pip install datetime
pip install lxml
pip install pyinstaller

其中
pip install pyinstaller
必不可少 

パッケージングパスの表示

次のステップは、exe が必要な py ファイルのパスを見つけることです。

小さな黒い箱の中でCDで解く

例えば:

ファイルはデスクトップ上のフォルダーに置かれているので、次のように入力します。

cd Desktop\a

パッケージ実行コマンド

Pyinstaller -F -w -i XXX(py文件名).py

実行中のプロセス表示

見栄えの良い写真を変更してロゴを作成したい場合

お気に入りの写真をオンラインで .ico 形式に変換できます (次のリンクで満足できます)

Image to ico-icoアイコン生成-オンラインツール

次に、.ico 形式の画像と .py ファイルを同じディレクトリに置きます。

使用

Pyinstaller -F -w -i XXX(图片转化ico后的名字).ico XXX(打包程序名).py

結果

最後に、このパスの下の dist ファイルにパッケージ化された exe プログラムを取得できます。

おすすめ

転載: blog.csdn.net/weixin_48572116/article/details/126118492