将输出抓取并写入文本文件

Scraping and writing output to text file

我使用 Python 2.7 编写了这个抓取程序,从 TrueLocal.com.au 的前 3 页中获取 links 并将它们写入文本文件。

当我运行程序时,只有第一个link被写入文本文件。我该怎么做才能将所有返回的 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)

您的问题是对于每个 link,您打开输出文件,写入它,然后再次关闭该文件。这不仅效率低下,而且除非您每次都以 "append" 模式打开文件,否则它只会被覆盖。实际上发生的事情是 last link 留在文件中,之前的所有内容都丢失了。

快速解决方法是将 open mode'w' 更改为 'a',但稍微重组您的程序会更好。现在 tru_crawler 函数负责抓取您的站点和写入输出;相反,让每个函数只负责一件事是更好的做法。

您可以将您的抓取功能变成一个 generator,一次产生 link 个,然后将生成的输出单独写入一个文件。将三行 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 函数 负责生成 URLs 爬行。如果您的爬虫接受 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 调用,或为其他 URL 模式创建不同的生成器,其余代码不需要改变!

默认情况下 'w' 是截断模式,您可能需要追加模式。参见:https://docs.python.org/2/library/functions.html#open.

也许将您的 href 附加到 while 循环中的列表,然后稍后写入文件看起来可读。或者按照建议使用 yield 以提高效率。

类似

with open('c:/test/true.txt', 'w') as fob:
    fob.writelines(yourlistofhref)

https://docs.python.org/2/library/stdtypes.html#file.writelines