采集数据的准备:
1.网页解析:Requests 这个是Python中的Python HTTP 神库
2.threading,queue,re,time 等系统模块
并没有使用采集框架,除Requests模块以外,其它完全使用标准库模块。
伪代码
workQueue = queue.Queue() #采集任务
threads[] 采集线程。
class Mythread: #创建工作线程
p_title = r'\d+\w+\d\d\d' #一些需要采集的正则
def doThreading() #线程中需要执行的任务
......
for i in work:
workQueue.put(item)#组装任务
#创建工作线程
for name in threadName:
thread = thread.Thread(name)
thread.start()#开始采集
threads.append(thread) #入队列
# 一直循环判断任务是否结束
while not workQueue.empty():
time.sleep(1)
#释放进程
for t in threads:
t.join()
保存文件或是加入数据库
遇到的一些坑(问题):
1.采集中遇到连接超时 长时间采集,网络连接超时会报out异常,线程自然就会结束,程序崩溃。 这个采用try捕获后,把当前失败的任务重新workQueue.put(item)#再次装回任务队列中
2.正则匹配不到,组装结果时报 None 异常 这个建议用if判断一下,如果没有匹配到结果后进行一下处理比较好,不然任务多起来,网页上各种情况都有可能的。
3.数据保存 一般保存没有什么大问题,主要是读取。 如果保存后是字符串,之前是list 或是 元组(Tuples)保存后就是字符串了,再读取就需要转换成对应的容器,这里用eval(s)函数方法,效果还是比较不错的。 还有就是大文本在读取的时候如果一次用python read()全部读取的时候会出现莫明的无反应及读取内容不全的情况 ,这里采用分段读取比较好些:
l = []
with open('test.txt', mode='r',encoding='utf-8') as f:
s = ''
while True:
temp = f.read(100)#分段读取,可以解决读取大文件时无法读取的奇怪问题
if temp == '':
break
s += temp
l = eval(s)
print(len(l))
f.close()
当然也可以直接入库,sqlite3当然是最佳的选择。
conn = sqlite3.connect('designlist.db')#创建数据库
cur = conn.cursor()#游标
#插入数据
for k in l:
v = (None,k[0],k[1],k[2],int(k[3]))
ins = "insert into tb values(?,?,?,?,?);"
cur.execute(ins, v)
conn.commit()#提交事务
conn.close#关闭连接
据说,这种方式插入数据可以防止SQL注入?
还就是多线程分配任务
多线程存在从wordQueue中抢任务的现象,有时只会有一二个线程在工作,其它线程都傻住不动,这里解决的方法就是在每个线程工作结束后让他休息sleep(0.001)秒,这样其它线程就有机会抢到工作了。
本贴主要是记录在多线程采集中遇到的坑,有问题可以和我一起探讨哈。