zoukankan      html  css  js  c++  java
  • 爬虫技术:携程爬虫阳光问政数据

    携程爬取阳光问帖子:进行了简单的数据存储,数据量共145226条,爬取时间为:3.65小时,实际时间感觉要多于统计时间。

    代码如下:

    import time
    import gevent
    import re
    import lxml
    import lxml.etree
    import requests
    import chardet
    
    
    def get_url_list(url):
        resp = requests.get(url)
        # 获取网页的编码格式,但是gb2312不能编码解码字节类型,只能换成gbk
        code_sytle = chardet.detect(resp.content)
        html_str = resp.content.decode("gbk")
        e = lxml.etree.HTML(html_str)
        count_str = e.xpath("//div[@class='pagination']/text()")[-1]
        # 获取帖子数量
        count = re.findall("(\d+)", count_str)[0]
        # 获取有多少页
        page_count = int(count) // 30
        url_list = list()
        for i in range(0, page_count + 1):
            url_list.append(url.format(i * 30))
        return url_list
    
    
    def get_per_page_info(url_list, f):
        for url in url_list:
            try:
                resp = requests.get(url=url,timeout=10)  # 此处容易出现长时间等待,因此加上超时设置
                html_str = resp.content.decode("gbk",errors="ignore")  # 此处容易出现解码错误,因此加上 erros="ignore"
                e = lxml.etree.HTML(html_str)
                tr_list = e.xpath("//div[@class='greyframe']//table[2]//table//tr")
                info_str = ""
                for tr in tr_list:
                    serial_num = tr.xpath(".//td[1]/text()")[0]
                    info_str += serial_num
                    info_str += " "
                    request_type = tr.xpath(".//td[2]//a[1]/text()")[0]
                    info_str += request_type
                    info_str += " "
                    request_reason = tr.xpath(".//td[2]//a[2]/text()")[0]
                    info_str += request_reason
                    info_str += " "
                    duty_department = tr.xpath(".//td[2]//a[3]/text()")[0]
                    info_str += duty_department
                    info_str += " "
                    status = tr.xpath(".//td[3]//span/text()")[0]
                    info_str += status
                    info_str += " "   
                    person = tr.xpath(".//td[4]/text()")   # 测试的过程中,此处容易越界,因此加入判断。
                    if len(person) == 0:
                        person = "MISS"
                        info_str += person
                    else:
                        person = tr.xpath(".//td[4]/text()")[0]
                        info_str += person
                    info_str += " "
                    time = tr.xpath(".//td[5]/text()")[0]
                    info_str += time
                    info_str += "\r\n "
                print(info_str)
                f.write(info_str)
    
            except Exception as e:
                print(e)
    
    if __name__ == '__main__':
        t = time.time()
        url = "http://wz.sun0769.com/index.php/question/report?page={}"
        url_list = get_url_list(url)
        f = open("sun_info.txt", "w", encoding="utf-8")
        # 任务切割,让10个携程去执行任务,每个携程传递url_list的一部分数据。
        xclist = [[], [], [], [], [], [], [], [], [], []]
        N = len(xclist)
        task_list = list()
        for i in range(len(url_list)):
            xclist[i % N].append(url_list[i])
        for i in range(N):
            task_list.append(gevent.spawn(get_per_page_info, xclist[i], f))
    
        gevent.joinall(task_list)
        f.close()
        print(time.time() - t)
    
    
    # 13162.275838851929 执行时间

    复习协程的知识:

    多线程会抢抢夺公共资源,因此会造成公共资源的不安全,需要通过线程锁进行解决,那么多个携程为什么不存在这个情况呢?

    因为多个协程也是在一个线程里面进行运行,只是在遇到IO堵塞操作时候,会自动切换到其他协程,让它们进行工作,此案例中,写入文件是一个IO操作,当一个协程写入文件时阻塞时,立马切换到其他协程进行数据的请求和筛选,合适的时机,在切换(此时应该是用到了上下文了,记录了数据写到哪里被阻塞了,切换回来继续在此处写入,这里概念比较模糊 # TODO 需要继续研究)到刚才读写操作的协程,进行数据写入。

  • 相关阅读:
    BETA版使用说明
    项目冲刺第二阶段Fifth Day
    第二阶段 项目冲刺Forth Day
    项目冲刺第二阶段Third Day
    项目冲刺第二阶段Second Day
    “渴了么”使用说明(供用户发表评论)
    项目冲刺第二阶段 每日站立会议First Day
    Alpha版总结会议
    alpha版使用说明书
    绩效考核
  • 原文地址:https://www.cnblogs.com/meloncodezhang/p/11443580.html
Copyright © 2011-2022 走看看