Python beautifulsoup解析速度的提高
目前,我已经编写了我的第一个python脚本,以便循环浏览CSV中列出的一些URL。超过14000个链接。我正在尝试1)获取所有关键字标签2)检查页面状态(404个链接需要标记)。3) 将youtube视频转换为嵌入的youtube链接(在可能转到网页获取关键字,然后转换为嵌入链接后) 车开得很慢,但我想不出更快的办法。我觉得这是request.get()属性,但我不知道如何加快速度。我只需要元数据,但它们是一种只获取页面开头而不是全部的方式吗?如何使此代码更好/更快/优化 在使用pyinstaller进行编译时,我还遇到了一个集合问题。我觉得我在使用Python3中的Python2代码。。当我使用python 3.5编写时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
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解析器,…好主意!但可能最好的做法是…此更改只是一个示例因为我不能运行它,所以我不能测试它。一个选项是一个我们都可以运行的更短的示例。