使用多线程改进Python抓取代码

时间:2017-09-17 22:12:25

标签: python multithreading csv web-scraping beautifulsoup

我正在使用urllib2,bsoup,csv编写一个简单的python爬虫......(Python 2.7) 我有一个.csv文件,其中存储了需要删除的url链接。

从下面的代码中,我正在从链接中抓取特定数字,以便从网站中找到最多一个与会者,并且crawl(url)功能正如整个代码一样正常工作。

from bs4 import BeautifulSoup
import json, csv, urllib2, urllib, re, time, lxml

def crawl(url):
    request = urllib2.Request(url, headers={"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36"})
    response = urllib2.urlopen(request)
    readd = response.read()

    soup = BeautifulSoup(readd, "lxml")
    response.close()
    maxx = 0
    if (soup.find("div", attrs={"class" : "attendees-placeholder placeholder"})):
        exists = soup.find("div", attrs={"class" : "attendees-placeholder placeholder"})
        nmb = exists.find("ul", "user-list")
        numbe = nmb.find_all("li")
        number = len(numbe)
        if (number > maxx):
            maxx = number
    else:
        number = 0

    print maxx



urls = csv.reader(open('all_links_2017.csv'))


for url in urls:
    crawl(url[0])

与此同时,由于我有大约100000个网址,因此速度太慢了。 我尝试了很多多线程样本,但这不是我的预期。 有没有办法改进这个代码,以便它可以更快? (即多线程,池...)

2 个答案:

答案 0 :(得分:1)

使用multiprocessing.Pool。将crawl更改为返回 maxx,而不是将其打印出来。然后使用multiprocessing.Pool.imap_unordered方法。

p = multiprocessing.Pool()
urls = csv.reader(open('all_links_2017.csv'))
for value in p.imap_unordered(crawl, [u[0] for u in urls]):
    print(value)

默认情况下,这将创建与CPU具有核心一样多的工作进程。

答案 1 :(得分:0)

你有没有尝试过?:

import threading

def crawl(url, sem):
    # Semaphore grabs a thread
    sem.acquire(blocking=False)
    # Your code here
    .
    .
    .
    # All the work is done (i.e. after print maxx)
    sem.release() 

sem = threading.Semaphore(4)
threads = [threading.Thread(target=crawl, args=(url, sem, )) for url in urls]

for thread in threads:
    thread.start()

修改:先将for更改为列表理解。

修改:添加了threading.Semaphore()限制方法。信号量是限制器(实质上是它的线程计数器),用于跟踪并发运行的线程数。在这种情况下,该值在任何给定时间最多设置为4个线程。如果您选择使用with,这也可以与BoundedSemaphore()上下文管理器一起使用。