美文网首页
selenium爬取某查查行业信息

selenium爬取某查查行业信息

作者: M4K0 | 来源:发表于2019-02-21 16:18 被阅读3次

    最近接到一个体力活儿,需要获取几百家企业的所属行业信息。某眼查需要登录,某查查免登录可用。由于水平有限,也为了节省时间,选用某查查。除此之外,脚本编写时暴露了许多的问题,需要后续深入研究,也都记录在本文中。
    update:2019-02-21 10:47:50

    技术要点:页面分析、多进程/多线程、文件读写同步、验证码问题、状态码问题、代理切换、动态加载数据获取、结果整合

    页面解析

    请求url:https://www.qichacha.com/search?key=公司全称
    打开链接后显示几个候选公司,第一个候选项匹配度最高。获取第一个候选项位置,和输入的公司名作比较,如果完全匹配,则继续。否则,视为查询不到结果。完全匹配后,需要点击公司名,进行一次跳转。再在页面中找到行业信息的位置,获取其内容。
    以上位置,可在chrome浏览器中用F12导出对应的xpath。
    部分代码如下:

    #-*-coding:utf-8-*-
    import sys
    reload(sys)
    sys.setdefaultencoding('utf8')
    
    import time
    import os
    import random
    from selenium import webdriver
    from multiprocessing import Process
    
    
    def get_Cominfo(id,fullname):
        id = str(id)
        url2 = 'https://www.qichacha.com/search?key='+fullname
     
        browser = webdriver.Firefox() 
        browser.get(url2)
        
        t1 = browser.find_elements_by_xpath('//*[@id="searchlist"]/table/tbody/tr/td[2]/a')
    
        ufname = unicode(fullname,"utf-8")
        if ufname == t1[0].text:
            h = t1[0].get_attribute('href')
            browser.get(h)
            
            t2 = browser.find_elements_by_xpath('//*[@id="Cominfo"]/table[2]/tbody/tr[5]/td[4]')
            res = t2[0].text      
            browser.quit()
    

    操作过程中发现,如果在第一个页面直接使用t1.click(),会再打开一个标签页,但browser对象仍然为第一个页面的。于是提取第一个页面中t1对应的url,也就是第二个页面中的url,用browser.get(h)直接从当前页面打开。最终res = t2[0].text就是找到的行业信息字符串。

    并发

    经测试发现,单条查询耗时20s~180s,都是卡在一些网页广告的加载上面了,比如p0.baidu.com、ali.cdn之类的。眼睁睁地看到了数据,但网页左上角的图标一直在转圈,程序也停在那里。也许可以不等它加载完就动态刷新抓取,但不知道怎么做……只尝试使用多进程处理。
    先把待查公司名存入一个txt文件中,每行一个。用python按行读取到一个列表中,遍历这个列表进行查询。多进程采用的multiprocessing模块,对每项开启一个进程,用time.sleep(random.randint(14,28))控制冷却时间,避免机器卡死。

    if __name__ == '__main__':
    
        print "[*] running..."
        comlist = get_Comlist('company.txt')
        start = time.time()
      
        for i in range(len(comlist)):
            if os.path.exists('result/'+str(i)+'.txt'):
                print "%s already exists, jump it" %str(i)
                continue
          
            p = Process(target=get_Cominfo,args=(i,comlist[i].strip(),))
         
            print 'Process %s  running...' %str(i)
            p.start()
            freeze = random.randint(14,28)
            print 'Next will start after %s seconds' %str(freeze)
            time.sleep(freeze)     
            
        p.join()
        print "Process end."    
    
        
        time.sleep(3000)
        end = time.time()
        print "[*] over! Cost seconds:",
        print end-start   
    

    保存结果时,开始采用的存入一个txt中,出现读写占用问题,报错一堆。如果要从python进程控制角度,又是资源锁、又是调度队列之类的,要在短时间内解决不太现实。不得不承认,这些东西没学扎实是真的,有空确实该巩固一些计算机基础了。说归说,业务问题还是要立刻马上解决的。如果一个文件不能解决问题,那就两个!实际上,对每一个结果都新建了一个txt,以行号id命名。最后汇总时,整理一下格式就好。

            s = file('result/'+id+'.txt','a')
            s.write(id)
            s.write('\t')
            s.write(fullname.strip())
            s.write('\t')
            s.write(res)
            s.write('\n')
            s.close()
    

    以上是保存每一条结果的代码,由于不知道process进程执行结果返回值在哪,便直接写到了get_Cominfo函数内部。有机会的话,把python的各种进程、线程同步问题扫一遍。

    对抗反爬虫

    程序运行一段时间开始报405错误,猜测是请求频率太高被封。反爬策略,有可能是根据浏览器UA判断,换个浏览器,还是405,看样子是封了ip。

    image.png

    换了个网,增大sleep时间,再次运行,一段时间后再次报错,提示输入验证码:滑动验证码+图片验证码。现在人工智能技术也有些进步,如果时间充足的话,selenium+OCR可以搞定。但是领导没有给那么多时间。多次检测发现,每个ip最多可以查50次,那么最简单粗暴的方法就是换ip!
    kali自带proxychains,改下配置文件sudo vi /etc/proxychains.conf,网上找些个代理用的ip,却发现各种运行报错。有时间再单独研究下。
    最后,手动配置linux的代理模式。

    image.png
    代理ip地址,挨个试咯。一个IP质量分两个方面,一个是本机到该ip的延迟,一个是该ip到目标网站的延迟情况。希望有朝一日能写个ip质量筛选脚本。其实github上这类挺多的,就是看着头昏眼花,先不管了。由此引申,根据延迟速度评估,或许能写个代理ip反查工具。
    比较逗的一个,刚连上ip,某查查立马提示输入验证码,看来用这种方法抓取某查查网站的不止我一个。更神奇的是,下意识地输入验证码,再运行第二个进程时,居然不需要验证了。

    结果汇总

    最终获取到如下文件:
    管道命令:cat *.txt>../multi.txt,python执行简单的shell命令可以用形如import os;os.system('ls')实现。
    排序问题,EXCEL中新建一个名为hangye的sheet,粘贴过去,手动排序。其实接下来的操作,没必要排序了。
    真实的待填充表格的行业信息是断断续续的,比如1~3行是空的,第4行又有了,5~9行又是待填数据。获取行业信息时,使用了电子表格的筛选功能,直接粘贴进去的话,会覆盖掉隐藏的行的数据,似乎只能手动一条一条粘贴了,400条数据,这要粘到猴年马月啊!一点都不酷!再写个脚本?于是有了下篇:Python操作EXCEL电子表格

    参考资料

    • 《Python爬虫开发与项目实战》
    • 《Python编程快速上手-让繁琐工作自动化》

    写在最后

    代码相当蹩脚,磕磕绊绊只比同事提前四五个小时完成,但成功地把重复性的任务转完成了创造性的工作。而且,学到了不少东西,还发现了自身的许多不足之处。总好过复制粘贴搜索刷到吐。

    相关文章

      网友评论

          本文标题:selenium爬取某查查行业信息

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