chuxuezhe7954
2018-04-23 12:53
采纳率: 33.3%
浏览 3.1k

python如何提高爬虫效率

任务背景是需要从一个linux服务器上下载文件,我拥有该服务器的访问权限但仅限于读。
目前的解决方法是我把所有需要下载的数据地址都保存在了本地的文件中,一行一条数据地址,通过paramiko包连接服务器然后使用多线程的方式进行爬取。每个线程启动时向其传入一个下载地址列表,因为每个线程的下载地址列表都不重复,因此不需要考虑线程之间的通信。详细代码如下:

# filename是存储在本地的地址列表文件,n是最大线程数
def download(filename, n):
    files = open(filename, 'rb').readlines()
    numbers = range(n)
    stop = len(files) / len(numbers)

    def thread_download(n):
        sftp = login()
        directory = files[n*stop : (n+1)*stop]
        for line in directory:
            # 该函数的功能是将服务器中的文件下载至本地,第一个参数是具体地址,第二个参数是连接句柄
            download_from_server(line.strip(), sftp) 

    threads = []
    for i in numbers:
        threads.append(threading.Thread(target=thread_download, args=(i, )))
        threads[i].start()
        time.sleep(0.1)  # 暂停0.1s是为了防止并发数太多

    for i in numbers:
        threads[i].join()

现在有两个问题:
(1)我一般把n设置为300,程序启动时下载速度很快,能够达到每分钟100多份文件,虽然也能看到一些线程崩溃,但数量不多;但是大概10分钟后程序下载速度只有20多份文件,是因为很多线程已经挂掉了嘛,还是线程之间通过同一个账户访问存在阻塞?为什么速度下降幅度这么大?
(2)除了使用多台机器和提高网速外,还能考虑什么方式提高爬虫效率?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

6条回答 默认 最新

  • blownewbee 2018-04-23 13:31

    首先要搞清楚瓶颈在哪里。一个是监控你的cpu、内存、io,看看有没有出现满载。一个是测试你的服务器的连接速度,确认它的上限,以及在持续传输的过程中是否会限速(有的机房会限速)

    点赞 打赏 评论
  • breaksss 2018-04-23 14:06

    一个进程开300个线程 太多了吧 建议少一点 16 or 32 测试一下 然后提高效率,基于目前的模式,你可以开多个进程 每个进程多个线程,可能会更快。

    点赞 打赏 评论
  • csdn1120628290 2018-04-23 14:24

    如果仅仅因为想要查找文档中的标签而将整片文档进行解析,实在是浪费内存和时间.最快的方法是从一开始就把标签以外的东西都忽略掉. SoupStrainer 类可以定义文档的某段内容,这样搜索文档时就不必先解析整篇文档,只会解析在 SoupStrainer 中定义过的文档. 创建一个 SoupStrainer 对象并作为 parse_only 参数给 BeautifulSoup 的构造方法即可

    目标文档

    from bs4 import BeautifulSoup, NavigableString
    from bs4 import SoupStrainer

    only_a_tags = SoupStrainer("a")
    only_tags_with_id_link2 = SoupStrainer(id="link2")

    def is_short_string(string):
    return len(string) < 6

    only_short_strings = SoupStrainer(text=is_short_string)

    soup = BeautifulSoup(html_doc, "lxml")
    print('1------------找到所有a元素')
    print(BeautifulSoup(html_doc, "html.parser", parse_only=only_a_tags).prettify())
    print('2------------找到id=link2的元素')
    print(BeautifulSoup(html_doc, "html.parser", parse_only=only_tags_with_id_link2).prettify())
    print('3------------找到元素长度小于10的元素')
    print(BeautifulSoup(html_doc, "html.parser", parse_only=only_short_strings).prettify())

    点赞 打赏 评论
  • qq_31995969 2018-04-23 14:55

    提高爬虫的方法有很多,建议看看python的相关库函数

    点赞 打赏 评论
  • lyhsdy 2018-08-28 01:27

    多线程并不会增加爬取速度,建议修改为多进程

    点赞 打赏 评论
  • ipidea全球HTTP 2020-07-14 15:08

    采集数据,都想尽量快的采集更多的数据,不然大量的工作还一条一条采集比较耗时。

    时间间隔访问,对于多少时间间隔进行采集,可以先测试目标网站所允许的最大访问频率,越贴近最大访问频率,越容易被封IP,这就需要设定一个合理的时间间隔,既能满足采集速度,也能不被限制IP。

    高匿名爬虫,需要突破网站的反爬虫机制就需要使用IP,利用换IP的方法进行多次访问。采用多线程也需要大量IP,使用高匿名代理ipidea来完成工作并能提高爬虫效率。

    点赞 打赏 评论