携程爬取阳光问帖子:进行了简单的数据存储,数据量共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 需要继续研究)到刚才读写操作的协程,进行数据写入。
原文地址:https://www.cnblogs.com/meloncodezhang/p/11443580.html
时间: 2024-10-11 05:03:36