刮擦并将输出写入文本文件

时间:2015-04-14 05:39:27

标签: python python-2.7 beautifulsoup

我使用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)

2 个答案:

答案 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