【问题标题】:Speed up scraping with Multithreading/Multiprocessing使用多线程/多处理加速抓取
【发布时间】:2020-05-24 22:53:18
【问题描述】:

我不知道如何在 python 中使用多线程/多处理来加速这个从 instagram 上的主题标签“猫”中获取所有用户名的抓取过程。
我的目标是尽可能快,因为目前这个过程有点慢

from instaloader import Instaloader

HASHTAG = 'cats'

loader = Instaloader(sleep=False)

users = []
for post in loader.get_hashtag_posts(HASHTAG):
    if post.owner_username not in users:
        users.append(post.owner_username) 
    print(post.owner_username)

【问题讨论】:

  • 使users 成为set() 而不是列表。对于多线程,可能会将帖子列表分成 4 个部分,并分别在 4 个线程中为它们执行循环。最后合并它们中的users 集合。
  • @AnmolSinghJaggi 你能告诉我吗?
  • 很快就会...
  • 好吧,我尝试运行程序并注意到它很慢,因为`loader.get_hashtag_posts(HASHTAG)` 是一个生成器,它以非常慢的速度返回帖子。所以这是 instaloader 库本身的问题,我们对此无能为力。但为了完整起见,我可能会写一个答案来展示当我有更多时间时如何使用多线程。
  • 更新:我实际上实现了多线程,它似乎确实以某种方式明显更快。已发布作为答案。万事如意!

标签: python performance optimization web-scraping python-multithreading


【解决方案1】:

LockedIterator 的灵感来自 here

import threading
from instaloader import Instaloader


class LockedIterator(object):
    def __init__(self, it):
        self.lock = threading.Lock()
        self.it = it.__iter__()

    def __iter__(self):
        return self

    def __next__(self):
        self.lock.acquire()
        try:
            return self.it.__next__()
        finally:
            self.lock.release()


HASHTAG = 'cats'
posts = Instaloader(sleep=False).get_hashtag_posts(HASHTAG)
posts = LockedIterator(posts)
users = set()


def worker():
    try:
        for post in posts:
            print(post.owner_username)
            users.add(post.owner_username)
    except Exception as e:
        print(e)
        raise


threads = []


for i in range(4):
    t = threading.Thread(target=worker)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

【讨论】:

  • 非常感谢你,工作就像魅力一样。目前我面临输出问题。我进行了一些更改,以获得一个包含主题标签的输入文件,然后它应该为每个主题标签创建一个包含所有用户名的输出文件,但我的脚本将所有内容导出到第一个 .txt 文件中,而不是每个应有的文件。我会在这个线程中发布代码^
【解决方案2】:

目标是有一个输入文件和单独的 output.txt 文件,也许你可以在这里帮助我

应该是第 45 行的东西

而且我不是很先进,所以我的尝试可能包含一些错误的代码,我不知道

作为 input.txt 的主题标签示例,我使用了: wqddt & d2deltas

from instaloader import Instaloader
import threading
import io
import time
import sys

class LockedIterator(object):
    def __init__(self, it):
        self.lock = threading.Lock()
        self.it = it.__iter__()

    def __iter__(self):
        return self

    def __next__(self):
        self.lock.acquire()
        try:
            return self.it.__next__()
        finally:
            self.lock.release()

f = open('input.txt','r',encoding='utf-8')
HASHTAG = f.read()
p = HASHTAG.split('\n')
PROFILE = p[:]

for ind in range(len(PROFILE)):
    pro = PROFILE[ind]

posts = Instaloader(sleep=False).get_hashtag_posts(pro)
posts = LockedIterator(posts)
users = set()

start_time = time.time()

PROFILE = p[:]

def worker():
    for ind in range(len(PROFILE)):
        pro = PROFILE[ind]
        try:
            filename = 'downloads/'+pro+'.txt'
            fil = open(filename,'a',newline='',encoding="utf-8")

            for post in posts:
                   hashtags = post.owner_username
                   fil.write(str(hashtags)+'\n')

        except:
            print('Skipping',pro)


threads = []

for i in range(4): #Input Threads
    t = threading.Thread(target=worker)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

end_time = time.time()
print("Done")
print("Time taken : " + str(end_time - start_time) + "sec")    

【讨论】:

    猜你喜欢
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 2015-02-10
    相关资源
    最近更新 更多