美文网首页
爬虫程序解析

爬虫程序解析

作者: 输配电世界 | 来源:发表于2020-02-21 10:31 被阅读0次

上一篇文档简单介绍了使用Python爬取招标网站的基本概念。在这个文档中,将说明爬虫的具体实现方法。

一、 整体业务流程

1)将目标网站录入到外部存储的Excel文档中,需要记录:招标网站的名称和网址

    # read tendering website list
#   csvPath='tendering2.csv'
#   df = pd.read_csv(csvPath, engine='python')
#   tenderDb = df.values
    tenderDb=np.array([
        ['北京地铁电子商务采购平台', r'http://www.bjmetro.com.cn/ecp/rfq'], 
        ['中煤招标有限责任公司', r'http://www.zmzb.com/gghw/index.jhtml']
        ])
#   tenderDb = pd.DataFrame({'company': data[:, 0], 'website': data[:, 1]})
    lenTDB = len(tenderDb)

这里为了便于调试,用一个数组替换了外部文件tendering2.csv

2)初始化配置文件和输出目录

    # initialize configuration files directory
    jasonPath = './jasonFiles'
    if not os.path.exists(jasonPath):
        os.makedirs(jasonPath)
    # initialize data storage files directory
    dbPath = './db'
    if not os.path.exists(dbPath):
        os.makedirs(dbPath)

如果用于配置的json文件夹不存在,那么创建这个文件夹。同样处理中间输出的结果

3)遍历招标网站

    for i in range(lenTDB):
        url = tenderDb[i,1].strip()
        jsonFile = re.sub(r'(.*://)?([^/?]+).*', '\g<2>', url)
        dbFile = os.path.join(dbPath, jsonFile + '.txt')
        jsonFile = os.path.join(jasonPath, jsonFile + '.json')

在这个过程中,首先将网站域名作为唯一值,并作为配置文件和输出文件的文件名,例如:北京地铁的配置文件应该是www.bjmetro.com.cn.json,输出文件为www.bjmetro.com.cn.txt

4)指定的网站读取特定的页面

        if os.path.exists(jsonFile):
            f = open(jsonFile,"rb")
            Cfg = json.load(f)
            f.close()
            f2 = open(dbFile,'w+',encoding='utf8')
            for page in Cfg['pages']:
                url = page['page']
                regEx = page['regex']
                group = page['group']
                strFetched = getPageContents(url)
                strFetched = re.sub(r"^\s+", "", strFetched, flags=re.M)
                #f2.write(strFetched)
                if regEx=='':
                    continue
                matches = re.finditer(regEx, strFetched, re.MULTILINE | re.DOTALL)
                print(tenderDb[i,0],url)
                print(regEx)
                print(len(strFetched))
                matchNum = 0
                for matchNum, match in enumerate(matches, start=1):
                    strScraped = ''
                    for i in group:
                        strScraped = strScraped + '\t' + match.group(i)
                    f2.write(strScraped.strip()+"\n\r")
                print(matchNum)
            f2.close()
        else:
            x = {
                "pages": [
                    {
                        "page": "",
                        "regex": "",
                        "group": [1,2,3]
                    }
                ]
            }
            with io.open(jsonFile, 'w') as db_file:
                db_file.write(json.dumps(x, indent=1))

在这一段代码中,如果配置文件存在,那么就根据配置文件读取页面。配置文件www.zmzb.com.json示例如下:

{
 "pages": [
  {
   "page": "http://www.zmzb.com/gghw/index.jhtml",
   "regex": "<li>\\s*<a\\shref=\\\"([^\\\"]*)\\\"\\starget=\\\"_blank\\\"\\stitle=\\\"([^\\\"]*)\\\">\\s*<span class=\\\"bidLink\\\">[^<]*<\/span>\\s*<span\\sclass=\\\"bidDate\\\" title=\\\"[^\\\"]*\\\">\\s*(\\d\\d\\d\\d-\\d\\d-\\d\\d)\\s*<\/span>\\s*<\/a>\\s*<\/li>",
   "group": [3, 2, 1]
  }
 ]
}

这是一个json,标准的数据交换格式。
为什么要在pages下面设置多个page呢?请各位思考
我们将一个页面(page)中的html读取后,保存在strFetched变量中,并将无用的空格去除。然后通过正则表达式regex,匹配出需要的内容,正则表达式使用括号对匹配结果进行分组,那么在json的group中定义了输出的组和顺序,在示例中为[3,2,1]表示,输出第3组匹配、第二组和第一组,并且顺序为3-2-1

匹配后得到的数据如下:

2020-02-14  中煤晋中能源化工有限责任公司下属九鑫公司2020年度洗油采购二次公告  http://www.zmzb.com:80/gghw/142625.jhtml

2020-02-14  中煤晋中能源化工有限责任公司下属九鑫公司2020年度纯碱采购二次公告  http://www.zmzb.com:80/gghw/142624.jhtml

2020-02-14  内蒙古中煤远兴能源化工有限公司变换催化剂、固体吸附剂采购项目【重新招标】终止公告    http://www.zmzb.com:80/gghw/142526.jhtml

2020-02-12  煤科集团沈阳研究院有限公司煤矿用激光甲烷遥测仪采购项目二次公告 http://www.zmzb.com:80/gghw/142503.jhtml

2020-02-12  平朔集团公司2020年1月第1批(包1-3)年度物资采购包2灯架等17项二次公告    http://www.zmzb.com:80/gghw/142489.jhtml

2020-02-12  平朔集团公司2020年2月第1批(包1-3)年度物资采购招标招标公告  http://www.zmzb.com:80/gghw/142482.jhtml

2020-02-11  平朔集团公司2020年1月第1批洗选中心空压机设备采购(CS19-4-1-10重新招标)招标公告    http://www.zmzb.com:80/gghw/142427.jhtml

2020-02-11  平朔集团公司2020年2月第1批(包2-5)长协寄售物资采购招标公告  http://www.zmzb.com:80/gghw/142426.jhtml

2020-02-11  中天合创能源有限责任公司 葫芦素煤矿矸石脱介振动筛采购二次公告 http://www.zmzb.com:80/gghw/142407.jhtml

2020-02-11  中煤科工集团上海有限公司采煤机安全准入分析验证实验室材料试验机采购二次公告   http://www.zmzb.com:80/gghw/142385.jhtml

2020-02-11  中煤科工集团上海有限公司采煤机安全准入分析验证实验室实时喷雾粒度分析仪采购二次公告   http://www.zmzb.com:80/gghw/142384.jhtml

2020-02-10  平朔集团公司2020年2月第1批(包4-6)年度物资采购招标公告    http://www.zmzb.com:80/gghw/142341.jhtml

2020-02-10  内蒙古中煤蒙大新能源化工有限公司埃利奥特配件(2001)采购二次公告  http://www.zmzb.com:80/gghw/142313.jhtml

2020-02-10  中煤鄂尔多斯能源化工有限公司阀门采购二次公告  http://www.zmzb.com:80/gghw/142292.jhtml

2020-02-10  中煤鄂尔多斯能源化工有限公司仪表材料采购二次公告    http://www.zmzb.com:80/gghw/142291.jhtml

2020-02-06  平朔集团公司2019年12月第2批能源化工(包1)物资采购 包1 二异丙基醚1项二次公告    http://www.zmzb.com:80/gghw/142153.jhtml

5)如果没有创建正则表达式

        else:
            x = {
                "pages": [
                    {
                        "page": "",
                        "regex": "",
                        "group": [1,2,3]
                    }
                ]
            }
            with io.open(jsonFile, 'w') as db_file:
                db_file.write(json.dumps(x, indent=1))

如果是第一次录入某个招标网站,会为该网站创建一个空的json
如果再次执行时,正则表达式regex没有定义,那么将跳过该记录

                if regEx=='':
                    continue
二、为什么要使用Selenium

为什么不能使用request直接抓取html呢?大家可以从本示例中北京地铁网站和中煤招标网站的html区别来找到答案,请各位思考...

def getPageContents(url):
    #options = Options()
    #options.add_argument("--headless")
    #driver = webdriver.Firefox(options=options, executable_path="C:\\Program Files\\Mozilla Firefox\\geckodriver.exe")
    options = webdriver.ChromeOptions()
    options.add_argument("headless")

    driver = webdriver.Chrome(options=options)
    driver.get(url)
    soup = BeautifulSoup(driver.page_source, 'html.parser')
    driver.quit()
    return(soup.prettify())
三、如何创建正则表达式

1)正则表达式的基本语法

从百度百科开始吧

2)正则表达式的检测

一个有用的正则表达式在线检测工具

3)在json中的正则表达式需要注意escape

四、还没有做的工作

1)爬取了数据后,被存储为txt或Excel文件。需要写个简单的逻辑,查询将要写入的新数据是否已经在文件中存在,即:是否是真正的新数据?
这个比较简单,留给大家完成。
2)发现新数据如何做出标记?并通过诸如:邮件、短信、微信发给相关的人
邮件可能比较简单
3)如何做到自动定期执行?
在linux上有cron定时命令,显然这是一个服务器环境,这个需要从整体规划考虑
4)如何实现过滤
这个比较简单实现,未来可以考虑订阅列表,不同的用户选择一组关键词,那么通过匹配关键词,向订阅用户发送新的招标信息。
5)按照规则补充其它网站、不同页面的json配置文件,编写正则表达式
有点工作量

相关文章

  • 爬虫

    总结爬虫流程:爬取--->解析--->存储什么是爬虫?请求网站并提取数据的自动化程序就叫做爬虫。爬虫的主要目的?是...

  • 爬虫程序解析

    上一篇文档简单介绍了使用Python爬取招标网站的基本概念。在这个文档中,将说明爬虫的具体实现方法。 一、 整体业...

  • 爬虫笔记

    爬虫:请求网站并提取数据的自动化程序。 爬虫的基本流程:发起请求 --> 获取响应的内容 --> 解析内容 -->...

  • 微信小程序之复杂富文本解析变通实现

    最近在写一个爬虫,需要将网页进行解析供微信小程序使用。文字和图片解析都好说,小程序也有对应的text和image标...

  • 我与编程21

    目前,我对爬虫的程序有了大致的了解:获取数据-解析数据-(提取数据)。 获取数据相对简单些,但是解析数据环节有点难...

  • 爬虫入门到放弃系列02:html网页如何解析

    前言 上一篇文章讲了爬虫的概念,本篇文章主要来讲述一下如何来解析爬虫请求的网页内容。 一个简单的爬虫程序主要分为两...

  • 如何判断页面的编码?

    在写爬虫程序(web页面)的时候,经常需要去解析页面的内容,而在解析前就必须要知道该页面是用何种字符集来编码的,这...

  • Python爬虫群作业-Week3-XPath

    加入爬虫群第三周,这周的作业是:008 - 爬虫处理流程及网页解析009 - 使用XPath解析网页010 - 使...

  • 爬虫基础系列urllib——构造请求头(3)

    爬虫与反爬虫 爬虫:自动获取网站数据的程序 反爬虫:使用技术手段防止爬虫程序爬取数据 反扒机制1 判断用户是否是浏...

  • 21 python多线程-线程进程协程并发,锁,死锁[pytho

    为什么要学习多线程 同一时间做了很多事情。 使用场景 1,快速高效的爬虫程序一个爬虫同时解析连接、爬取文字、爬取图...

网友评论

      本文标题:爬虫程序解析

      本文链接:https://www.haomeiwen.com/subject/apwqqhtx.html