Python beautifulsoup解析速度的提高

Python beautifulsoup解析速度的提高,python,performance,python-3.x,beautifulsoup,Python,Performance,Python 3.x,Beautifulsoup,目前,我已经编写了我的第一个python脚本,以便循环浏览CSV中列出的一些URL。超过14000个链接。我正在尝试1)获取所有关键字标签2)检查页面状态(404个链接需要标记)。3) 将youtube视频转换为嵌入的youtube链接(在可能转到网页获取关键字,然后转换为嵌入链接后) 车开得很慢,但我想不出更快的办法。我觉得这是request.get()属性,但我不知道如何加快速度。我只需要元数据,但它们是一种只获取页面开头而不是全部的方式吗?如何使此代码更好/更快/优化 在使用pyinsta

目前,我已经编写了我的第一个python脚本,以便循环浏览CSV中列出的一些URL。超过14000个链接。我正在尝试1)获取所有关键字标签2)检查页面状态(404个链接需要标记)。3) 将youtube视频转换为嵌入的youtube链接(在可能转到网页获取关键字,然后转换为嵌入链接后)

车开得很慢,但我想不出更快的办法。我觉得这是request.get()属性,但我不知道如何加快速度。我只需要元数据,但它们是一种只获取页面开头而不是全部的方式吗?如何使此代码更好/更快/优化

在使用pyinstaller进行编译时,我还遇到了一个集合问题。我觉得我在使用Python3中的Python2代码。。当我使用python 3.5编写时

import requests
from bs4 import BeautifulSoup
import csv
import re
import time

linkLocation = r'C:\Users\JCModern\Desktop\content_links.csv'
source_code = ''
myURL = ''
timestr = time.strftime("%Y%m%d_%H%M%S")
newfilename = r'C:\Users\JCModern\Desktop\content_links_and_keywords_' + timestr + '.csv'

with open(newfilename, "w", newline='') as file:
    writer = csv.writer(file, delimiter=',')
    writer.writerow(('cmsid', 'filepath', 'metatags', 'pageurl', 'pageurlchange'))
file.close()
with open(linkLocation, "r", encoding="utf-8-sig") as f:
    csv_f = csv.reader(f, delimiter=",")
    next(csv_f, None)
    for row in csv_f:
        if len(row) != 0:
            # init variables
            myKeywords = ""
            myTitle = ''
            myURL = ''
            pageUrlChange = ''
            pageStatus = ''
            pageUrl = ''
            myCmsid = (row[0])
            myURL = (row[2])
            if "https://www.youtube.com/embed/" in myURL:
                youtubeurl = myURL.split('/')
                youtubeurl = youtubeurl[4]
                youtubeurl = re.sub(
                    r'\?|\&|\=|re(l=\d+|l)|featur(e=sub|e)|playnext|video(s=\w+|s)|watch|_?((youtu(\.be|be))|fro(m=TL|m)|gdata|player|lis(t=\w+|t)|(inde(x=\w+|x)))_?|(v|vi)=|channel|ytscreeningroom','', youtubeurl)
                myURL = 'https://www.youtube.com/watch?v=' + youtubeurl
            try:    
                source_code = requests.get(myURL)
            except Exception:
                with open('errors.txt', 'a', newline='') as file:
                    writer = csv.writer(file, delimiter=',')
                    writer.writerow((myCmsid, myURL))
                file.close()
            pageStatus = source_code.status_code
            plain_text = source_code.text
            soup = BeautifulSoup(plain_text, 'html.parser')
            pageStatus = str(pageStatus)
            pageStatus = pageStatus[:1]
            pageStatus = int(pageStatus)
            if pageStatus == 2:
                pageUrlChange = 0
            else:
                pageUrlChange = 1
            if pageStatus == 3:
                pageUrl = source_code.url
            l = soup.findAll("meta", attrs={"name": "keywords"})
            if l is None:
                myKeywords = ""
            else:
                try:
                    myKeywords = l[0]['content']
                except:
                    myKeywords = myKeywords
                myKeywords = myKeywords.replace(', ', '~')
                myKeywords = myKeywords.replace(',', '~')
                myKeywords = myKeywords.replace('(', '')
                myKeywords = myKeywords.replace(')', '')
            if soup.find('title'):
                myTitle = soup.find('title').string
            if "https://www.youtube.com/" in myURL:
                youtubeurl = myURL.split('/')
                youtubeurl = youtubeurl[3]
                youtubeurl = re.sub(r'\?|\&|\=|re(l=\d+|l)|featur(e=sub|e)|playnext|video(s=\w+|s)|watch|_?((youtu(\.be|be))|fro(m=TL|m)|gdata|player|lis(t=\w+|t)|(inde(x=\w+|x)))_?|(v|vi)=|channel|ytscreeningroom','', youtubeurl)
                myURL = 'https://www.youtube.com/embed/' + youtubeurl
#                print(youtubeurl)
            if "https://youtu.be/" in myURL:
                youtubeurl = myURL.split('/')
                youtubeurl = youtubeurl[3]
                youtubeurl = re.sub(
                    r'\?|\&|\=|re(l=\d+|l)|featur(e=sub|e)|playnext|video(s=\w+|s)|watch|_?((youtu(\.be|be))|fro(m=TL|m)|gdata|player|lis(t=\w+|t)|(inde(x=\w+|x)))_?|(v|vi)=|channel|ytscreeningroom','', youtubeurl)
                myURL = 'https://www.youtube.com/embed/' + youtubeurl
#                print(youtubeurl)
#            print((myCmsid, myURL, myKeywords, pageUrl, pageUrlChange))
            with open(newfilename, "a", newline='') as file:
                writer = csv.writer(file, delimiter=',')
                writer.writerow((myCmsid, myURL, myKeywords, pageUrl, pageUrlChange))
            file.close()
f.close()

解析器是一个使用正则表达式的纯python实现。你真的不想用它。安装
lxml
并改用C代码进行解析(请记住使用
BeautifulSoup(纯文本,'lxml')

您也不希望继续重新打开CSV文件。请在循环外部打开它一次,然后只需将新行写入循环中的
CSV.writer()
对象即可


否则,你无法加快URL加载的速度,也不能太快。网络速度总是一个瓶颈。你可以使用非常低的级别,但我怀疑它所能提供的加速会在这里产生影响。

除了建议使用更快的xml解析器外,这也是通过
进行并行化的一个很好的候选方法多处理
模块。我已重新排列了您的代码,以便在可以委托给子流程的工作进程中执行请求/解析。工作进程返回需要添加到csv的行。我在返回行的前面添加了0/-1错误代码,以便父进程知道哪个csv获得结果

import requests
from bs4 import BeautifulSoup
import csv
import re
import time
import multiprocessing
import traceback

def grabber(myCmsid, myURL):
    try:
        return grabber_impl(myCmsid, myURL)
    except:
        return (-1, myCmsid, myURL, traceback.format_exc())

def grabber_impl(myCmsid, myURL):
    # init variables
    myKeywords = ""
    myTitle = ''
    myURL = ''
    pageUrlChange = ''
    pageStatus = ''
    pageUrl = ''
    if "https://www.youtube.com/embed/" in myURL:
        youtubeurl = myURL.split('/')
        youtubeurl = youtubeurl[4]
        youtubeurl = re.sub(
            r'\?|\&|\=|re(l=\d+|l)|featur(e=sub|e)|playnext|video(s=\w+|s)|watch|_?((youtu(\.be|be))|fro(m=TL|m)|gdata|player|lis(t=\w+|t)|(inde(x=\w+|x)))_?|(v|vi)=|channel|ytscreeningroom','', youtubeurl)
        myURL = 'https://www.youtube.com/watch?v=' + youtubeurl

    source_code = requests.get(myURL)
    pageStatus = source_code.status_code
    plain_text = source_code.text
    soup = BeautifulSoup(plain_text, 'html.parser')
    pageStatus = str(pageStatus)
    pageStatus = pageStatus[:1]
    pageStatus = int(pageStatus)
    if pageStatus == 2:
        pageUrlChange = 0
    else:
        pageUrlChange = 1
    if pageStatus == 3:
        pageUrl = source_code.url
    l = soup.findAll("meta", attrs={"name": "keywords"})
    if l is None:
        myKeywords = ""
    else:
        try:
            myKeywords = l[0]['content']
        except:
            myKeywords = myKeywords
        myKeywords = myKeywords.replace(', ', '~')
        myKeywords = myKeywords.replace(',', '~')
        myKeywords = myKeywords.replace('(', '')
        myKeywords = myKeywords.replace(')', '')
    if soup.find('title'):
        myTitle = soup.find('title').string
    if "https://www.youtube.com/" in myURL:
        youtubeurl = myURL.split('/')
        youtubeurl = youtubeurl[3]
        youtubeurl = re.sub(r'\?|\&|\=|re(l=\d+|l)|featur(e=sub|e)|playnext|video(s=\w+|s)|watch|_?((youtu(\.be|be))|fro(m=TL|m)|gdata|player|lis(t=\w+|t)|(inde(x=\w+|x)))_?|(v|vi)=|channel|ytscreeningroom','', youtubeurl)
        myURL = 'https://www.youtube.com/embed/' + youtubeurl
#                print(youtubeurl)
    if "https://youtu.be/" in myURL:
        youtubeurl = myURL.split('/')
        youtubeurl = youtubeurl[3]
        youtubeurl = re.sub(
            r'\?|\&|\=|re(l=\d+|l)|featur(e=sub|e)|playnext|video(s=\w+|s)|watch|_?((youtu(\.be|be))|fro(m=TL|m)|gdata|player|lis(t=\w+|t)|(inde(x=\w+|x)))_?|(v|vi)=|channel|ytscreeningroom','', youtubeurl)
        myURL = 'https://www.youtube.com/embed/' + youtubeurl
#                print(youtubeurl)
#            print((myCmsid, myURL, myKeywords, pageUrl, pageUrlChange))
    return (0, myCmsid, myURL, myKeywords, pageUrl, pageUrlChange))


linkLocation = r'C:\Users\JCModern\Desktop\content_links.csv'
source_code = ''
myURL = ''
timestr = time.strftime("%Y%m%d_%H%M%S")
newfilename = r'C:\Users\JCModern\Desktop\content_links_and_keywords_' + timestr + '.csv'

with open(linkLocation, "r", encoding="utf-8-sig") as f:
    csv_f = csv.reader(f, delimiter=",")
    next(csv_f, None)
    pool = multiprocessing.Pool()

    with open(newfilename, 'a', newline='') as out, open('errors.txt', 'a', newline='') as err:
        writer = csv.writer(out, delimiter=',')
        err_writer = csv.writer(err, delimiter=',')
        for result in pool.imap_unordered(grabber, ((row[0], row[2]) for row in csv_f if row), chunksize=1):
            if result[0]:
                writer.writerow(result[1:])
            else:
                print(result[3])
                err_writer.writerow(result[1:3])
pool.close()
pool.join()

下面有两个有价值的答案,我正准备写关于.lxml和多处理(如果你有2+个内核的话)还考虑了LeCeCH模块。我很感激这个回复,但是这个代码实际上并没有做任何事情。我让它运行了15分钟,现在出错了。TXT文件被创建了,但是没有任何内容,并且创建了CordunthLink和SyKiWorsStDAT.CSV文件,但是没有任何内容。我没有注释“打印”。(myCmsid、myURL、myKeywords、pageUrl、pageUrlChange))“并且从不返回任何内容我更新了示例,使异常处理程序覆盖整个工作进程。
Pool.imap\u unordered
将在父进程中重新释放执行,这可能是您的问题。我看到您试图更改代码以获得更好的html解析器,…好主意!但可能最好的做法是…此更改只是一个示例因为我不能运行它,所以我不能测试它。一个选项是一个我们都可以运行的更短的示例。