【问题标题】:Unable to execute my script in the right way using thread无法使用线程以正确的方式执行我的脚本
【发布时间】:2019-02-10 22:53:27
【问题描述】:

我尝试使用 python 结合 Thread 创建一个爬虫,以缩短执行时间。刮板应该解析所有商店名称以及遍历多个页面的电话号码。

脚本正在运行,没有任何问题。由于我对与 Thread 合作非常陌生,因此我很难理解我的做法是否正确。

这是我迄今为止尝试过的:

import requests 
from lxml import html
import threading
from urllib.parse import urljoin 

link = "https://www.yellowpages.com/search?search_terms=coffee&geo_location_terms=Los%20Angeles%2C%20CA&page={}"

def get_information(url):
    for pagelink in [url.format(page) for page in range(20)]:
        response = requests.get(pagelink).text
        tree = html.fromstring(response)
        for title in tree.cssselect("div.info"):
            name = title.cssselect("a.business-name span[itemprop=name]")[0].text
            try:
                phone = title.cssselect("div[itemprop=telephone]")[0].text
            except Exception: phone = ""
            print(f'{name} {phone}')

thread = threading.Thread(target=get_information, args=(link,))

thread.start()
thread.join()

问题是 无论我使用 Thread 运行上述脚本,我都找不到时间或性能方面的任何差异 > 或不使用 Thread。如果我出错了,如何使用 Thread 执行上述脚本?

编辑:我尝试更改逻辑以使用多个链接。现在有可能吗?提前致谢。

【问题讨论】:

  • 由于全局解释器锁 (GIL),线程很少会使代码更快
  • 这是一个启动一个线程的单个进程。正在执行的工作没有并发,因此执行时间大致相同。
  • 将单个进程包装到线程中只会让你的脚本变慢...你应该并行运行多个进程以减少执行时间
  • 如果您需要抓取多个链接,您可以尝试同时抓取它们(几乎同时如提到的那样,GIL 不允许同时实际运行进程)thread1 = threading.Thread(target=get_information, args=(link1,)); thread2 = threading.Thread(target=get_information, args=(link2,)); etc
  • 请查看编辑,看看现在是否有任何选项可以提高性能。感谢大家提供宝贵的 cmets。

标签: python python-3.x web-scraping lxml python-multithreading


【解决方案1】:

您可以使用线程并行抓取多个页面,如下所示:

import requests
from lxml import html
import threading
from urllib.parse import urljoin

link = "https://www.yellowpages.com/search?search_terms=coffee&geo_location_terms=Los%20Angeles%2C%20CA&page={}"

def get_information(url):
    response = requests.get(url).text
    tree = html.fromstring(response)
    for title in tree.cssselect("div.info"):
        name = title.cssselect("a.business-name span[itemprop=name]")[0].text
        try:
            phone = title.cssselect("div[itemprop=telephone]")[0].text
        except Exception: phone = ""
        print(f'{name} {phone}')

threads = []
for url in [link.format(page) for page in range(20)]:
    thread = threading.Thread(target=get_information, args=(url,))
    threads.append(thread)
    thread.start()
for thread in threads:
    thread.join()

请注意,不会保留数据序列。这意味着如果要逐页抓取提取的数据序列将是:

page_1_name_1
page_1_name_2
page_1_name_3
page_2_name_1
page_2_name_2
page_2_name_3
page_3_name_1
page_3_name_2
page_3_name_3

while with Threading 数据将被混合:

page_1_name_1
page_2_name_1
page_1_name_2
page_2_name_2
page_3_name_1
page_2_name_3
page_1_name_3
page_3_name_2
page_3_name_3

【讨论】:

  • 对不起,我的反应迟了,先生。它工作得非常完美。
  • 我一直在等待您的在线可用性@sir Andersson。如果您不忙,请查看this post。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-28
  • 2018-09-09
  • 2015-10-07
相关资源
最近更新 更多