多线程爬虫

看着那个key的网站着实简陋,决定给它加点新功能,于是准备爬虫获取每个游戏的当前价格和历史最低价

刚开始,我准备干脆把所有steam游戏的价格都爬到数据库里,然后我有什么key直接查数据库出价格

看了几个提供这种接口的网站,挑了个比较好抓取的:isthereanydeal 看了看他有一个接口是get方法中提供游戏名称即可返回一份json数据,里面包含了价格信息,就决定用它了

首先从g胖那边拿到了当天完整的steam游戏清单(api地址) 先验证一下,粗略猜了一下他的游戏名称规则,大写改小写,空格删除,加号改plus,然后开始循环爬

数据是爬到了,可是一分钟才没几条(这网站服务器在外国,光ping就有230的延迟,还丢包),那得开多线程啊

我定义多线程的任务分配是这样:设定一个步长,第一个线程执行第一个任务,第二个线程执行第二个任务……第一个线程执行完后,开始执行第步长+1个任务,如此循环直到所有任务结束

那么每个子线程需要传入的的东西是:开始位置(自己是第几个线程)、结束位置(有几个任务)、步长(总的线程数)、游戏名称库(这里感觉可以优化下,我把这个库传给了所有线程让他们自己处理)。除此之外,由于我最后让各子线程将结果写入一个公共数组,所以还有一个线程锁

class Worker(threading.Thread):
    def __init__(self, stage, data, data_len, thread_num, lk):
        threading.Thread.__init__(self)
        self.stage = stage
        self.data = data
        self.len = data_len
        self.lock = lk
        self.step = thread_num
    def run(self):
        for i in range(self.stage, self.len, self.step):
            #do next

由于感觉前面速度太慢,我一下开了50个线程

thread_num = 5
    for i in range(thread_num):
        worker = Worker(i, data, data_len, thread_num, lock)
        threads.append(worker)
        worker.start()
    for worker in threads:  #等待线程结束
        worker.join()

配上一些字符串操作,一下就抓到了很多价格,不过大部分游戏价格还没有抓取到,这个等会再处理,然后我决定去吃个饭回来看看效率到底咋样

等我回来的时候,我看到我连接服务器失败了=-=试着再去ping也不通了,服务器把我ip拉黑了(哭)

再查了查requests的文档,发现他有代理的功能,网上找了个端口开放的主机,拿他当个跳板。但是获取所有游戏价格的计划好像行不通,就算50线程也得至少半小时,而且会被封ip,那就退而求其次吧,把我有的key的价格查出来就行了,然后线程数也被我降低到了5

还得解决一下大部分游戏获取不到的问题,针对问题,有两个解决路径
1.尝试很多游戏的正常查询,继续猜它的get解析格式
2.访问查询页,从html中提取接口正确地址

从道理上来讲,只要游戏在网站中收录了,2方法肯定行得通,但是走这个方法会访问两次服务器,对资源的开销会成倍上升,速度也会下降,所以我先尽量使用1方法,若实在找不到,就使用2

根据我对一些游戏请求路径的仔细研究,写出了转换函数(小写+the去除+罗马数字+特殊符号去除):

str_before = ['the', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', 'é', 'ê']
str_after = ['', 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix', 'plus', 'e', 'e']

def change_format(str_in):
    str_in = str_in.lower()    #小写
    for i in range(12):     #替换
        str_in = str_in.replace(str_before[i], str_after[i])
    str_in = filter(str.isalnum, str_in)  #去除特殊符号
    str_in = ''.join(list(str_in))
    return str_in

2方法就不用多讲了,研究下html的格式,用正则循环提取即可

放个成品页:http://duya12345.top:39122/visitor

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注