【发布时间】:2017-01-22 20:23:10
【问题描述】:
这是一个代码:
str_regex = '(https?:\/\/)?([a-z]+\d\.)?([a-z]+\.)?activeingredients\.[a-z]+(/?(work|about|contact)?/?([a-zA-z-]+)*)?/?'
import urllib.request
from Stacks import Stack
import re
import functools
import operator as op
from nary_tree import *
url = 'http://www.activeingredients.com/'
s = set()
List = []
url_list = []
def f_go(List, s, url):
try:
if url in s:
return
s.add(url)
with urllib.request.urlopen(url) as response:
html = response.read()
#print(url)
h = html.decode("utf-8")
lst0 = prepare_expression(list(h))
ntr = buildNaryParseTree(lst0)
lst2 = nary_tree_tolist(ntr)
lst3= functools.reduce(op.add, lst2, [])
str2 = ''.join(lst3)
List.append(str2)
f1 = re.finditer(str_regex, h)
l1 = []
for tok in f1:
ind1 = tok.span()
l1.append(h[ind1[0]:ind1[1]])
for exp in l1:
length = len(l1)
if (exp[-1] == 'g' and exp[length - 2] == 'p' and exp[length - 3] == 'j') or \
(exp[-1] == 'p' and exp[length - 2] == 'n' and exp[length - 3] == 'g'):
pass
else:
f_go(List, s, exp, iter_cnt + 1, url_list)
except:
return
它基本上使用 urllib.request.urlopen 在循环中递归地打开 url;是否在某个域中(在这种情况下为 activeingredients.com);从页面中提取链接是通过正则表达式完成的。在里面,打开页面它会解析它并作为字符串添加到列表中。因此,假设要做的是遍历给定的域,提取信息(在这种情况下是有意义的文本),添加到列表中。尝试 except 块,只在所有 http 错误的情况下返回(以及所有其他错误,但这是经过测试和工作的)。
例如,它适用于这个小页面,但对于更大的页面非常慢并且会占用内存。
解析,准备页面,我相信或多或少地做正确的工作。
问题是,有没有一种有效的方法来做到这一点?网络搜索如何如此快速地通过网络爬行?
【问题讨论】:
-
如果这是工作代码,请参阅Code Review。但是你为什么是parsing HTML with regex?
-
在我看来,您绝对应该使用多线程,因为大部分时间您都在等待网络内容。您应该同时发送多个请求。
-
这是一个很好的问题,但答案很复杂。对于初学者,您应该使用数据库来存储数据,这样就不需要将整个数据集加载到内存中。此外,您应该并行加载多个 Web 请求。但是,是的,这是一项复杂的任务。也许尝试寻找一个现有的库来做到这一点?
-
@jonrsharpe:更糟糕的是:对内容使用迭代器并检查每个字符。
-
图书馆推荐与 SO 无关。
标签: python html web web-crawler