pb_*_*_ng 3 python beautifulsoup python-2.7
我使用Python 2.7编写了这个刮刀,从TrueLocal.com.au的前3页获取链接,并将它们写入文本文件.
当我运行程序时,只有第一个链接写在文本文件中.我可以做什么,以便返回的所有URL都写在文件上?
import requests
from bs4 import BeautifulSoup
def tru_crawler(max_pages):
page = 1
while page <= max_pages:
url = 'http://www.truelocal.com.au/find/car-rental/' + str(page)
code = requests.get(url)
text = code.text
soup = BeautifulSoup(text)
for link in soup.findAll('a', {'class':'name'}):
href = 'http://www.truelocal.com.au' + link.get('href')
fob = open('c:/test/true.txt', 'w')
fob.write(href + '\n')
fob.close()
print (href)
page += 1
#Run the function
tru_crawler(3)
Run Code Online (Sandbox Code Playgroud)
您的问题是,对于每个链接,您打开输出文件,写入,然后再次关闭该文件.这不仅效率低,而且除非您每次以"追加"模式打开文件,否则它将被覆盖.实际上发生的事情是最后一个链接留在文件中,之前的所有内容都丢失了.
快速解决将是改变开放模式从'w'到'a',但它会是更好的小幅调整你的计划.现在,该tru_crawler功能负责抓取您的网站和编写输出; 相反,更好的做法是让每个功能只负责一件事.
您可以将爬网功能转换为一次生成一个链接的生成器,然后将生成的输出分别写入文件.将这fob三行替换为:
yield href + '\n'
Run Code Online (Sandbox Code Playgroud)
然后,您可以执行以下操作:
lines = tru_crawler(3)
filename = 'c:/test/true.txt'
with open(filename, 'w') as handle:
handle.writelines(lines)
Run Code Online (Sandbox Code Playgroud)
还要注意使用with statement; 打开文件使用with一旦该块结束就自动关闭它,从而使您不必close()自己打电话.
将生成器和任务分离的思想更进一步,您可能会注意到该tru_crawler函数还负责生成要爬网的URL列表.如果您的抓取工具接受可迭代的URL而不是自己创建URL,那么也可以分离出来.就像是:
def make_urls(base_url, pages):
for page in range(1, pages+1):
yield base_url + str(page)
def crawler(urls):
for url in urls:
#fetch, parse, and yield hrefs
Run Code Online (Sandbox Code Playgroud)
然后,而不是呼叫tru_crawler(3),它变成:
urls = make_urls('http://www.truelocal.com.au/find/car_rental/', 3)
lines = crawler(urls)
Run Code Online (Sandbox Code Playgroud)
然后按上述步骤进行.
现在,如果您想要抓取其他网站,您只需更改您的make_urls呼叫,或为其他网址模式创建不同的生成器,其余代码无需更改!