我使用Python 2.7对此刮刀进行编码,以从TrueLocal.com.au的前3页获取链接,并将它们写入文本文件。
当我运行程序时,只有第一个链接写在文本文件中。我该怎么办才能将返回的所有网址写在文件上?
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)
答案 0 :(得分:6)
您的问题是,对于每个链接,您打开输出文件,写入,然后再次关闭该文件。这不仅效率低下,而且除非你在&#34中打开文件;追加&#34;每次模式,它都会被覆盖。实际上发生的事情是 last 链接留在文件中,之前的所有内容都将丢失。
快速解决方法是将open mode从'w'
更改为'a'
,但稍微调整一下您的程序会更好。现在tru_crawler
函数负责抓取您的网站和编写输出;相反,让每个功能只对一件事负责是一种更好的做法。
您可以将抓取功能转换为generator,一次生成一个链接,然后将生成的输出分别写入文件。将以下三个fob
行替换为:
yield href + '\n'
然后您可以执行以下操作:
lines = tru_crawler(3)
filename = 'c:/test/true.txt'
with open(filename, 'w') as handle:
handle.writelines(lines)
另请注意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
然后,它不再是tru_crawler(3)
,而是变成:
urls = make_urls('http://www.truelocal.com.au/find/car_rental/', 3)
lines = crawler(urls)
然后按上述步骤继续。
现在,如果您想抓取其他网站,只需更改make_urls
电话,或为其他网址模式创建不同的生成器,其余代码也无需更改!< / p>
答案 1 :(得分:2)
默认情况下,'w'是截断模式,您可能需要追加模式。请参阅:https://docs.python.org/2/library/functions.html#open。
也许将你的hrefs附加到while循环中的列表中,然后写入文件看起来可读。或者根据建议使用yield
来提高效率。
像
这样的东西with open('c:/test/true.txt', 'w') as fob:
fob.writelines(yourlistofhref)
https://docs.python.org/2/library/stdtypes.html#file.writelines