【问题标题】:Writing CSV file while looping through web pages循环浏览网页时写入 CSV 文件
【发布时间】:2015-03-04 18:43:53
【问题描述】:

这是我之前关于循环浏览多个网页的问题的后续问题。我是编程新手...感谢您的耐心和非常明确的解释!

我已经编写了一个遍历许多网页的循环。在每一页上,我想抓取数据,将其保存到变量或 csv 文件(以更容易/更稳定的为准),然后单击“下一步”按钮,在第二页上抓取数据并将其附加到变量或csv文件等。

具体来说,我的代码如下所示:

url="http://www.url.com"
driver = webdriver.Firefox()
driver.get(url)
(driver.page_source).encode('utf-8')
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html)

wait = WebDriverWait(driver, 10)

while True:
    # some code to grab the data
    job_tag={'class': re.compile("job_title")}
    all_jobs=soup.findAll(attrs=job_tag)
    jobs=[]
    for text in (all_jobs):
     t=str(''.join(text.findAll(text=True)).strip()) 
     jobs.append(t)

    writer=csv.writer(open('test.csv','a', newline=''))
    writer.writerows(jobs)

    # click next link
   try:
       element=wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='reviews']/a/span[starts-with(.,'Next')]")))
       element.click()
   except TimeoutException:
        break 

它运行没有错误,但是 1)该文件一遍又一遍地收集第一页的数据,而不是后续页面的数据,即使循环执行正确(最终,我并不介意重复条目,但我确实想要来自所有页面的数据)。 我怀疑我需要为每个新页面“重新定义”汤,我正在研究如何让 bs4 访问这些网址。

2) 最后一页没有“下一页”按钮,因此代码不会附加最后一页的数据(当我在 csv 行中使用 'w' 而不是 'a' 时出现该错误,数据为将倒数第二页写入 csv 文件)。

此外,虽然这是一个小问题,但数据在 csv 中每个单元格写入一个字母,即使当我在 Python 中使用 bs4 运行该部分时,数据的格式也正确。我错过了什么?

谢谢!

【问题讨论】:

  • jobsall_jobs 是如何定义的?您可能需要在每次迭代时重置 jobs 变量以防止重复现有行。
  • @augurar 我编辑了帖子以反映它们的定义方式。谢谢。

标签: python loops csv


【解决方案1】:

我怀疑我需要为每个新页面“重新定义”汤

确实,您应该这样做。你看,你的while 循环运行时soup 总是引用你在进入while 循环之前创建的同一个旧对象。您应该将soup 重新绑定到一个新的BeautifulSoup 实例,这很可能是您在最后几行中找到的anchor(标签a)后面的URL:

element=wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='reviews']/a/span[starts-with(.,'Next')]")))

你可以只用你的soup 来访问它(请注意,我没有测试它的正确性:我猜没有页面的实际来源):

next_link = soup.find(id='reviews').a.get('href')

然后,在您的 while 循环结束时,您将重新绑定 soup

soup = BeautifulSoup(urllib.request.urlopen(next_link.read()))

您仍然应该添加一个try - except 子句来捕获当它找不到最后一个“Next”链接然后跳出循环时它将在最后一页上生成的错误。

请注意,selenium 对于您的用例很可能不需要,bs4 就足够了(但两者都可以)。

此外,虽然这是一个小问题,但数据在 csv 中每个单元格写入一个字母,即使当我在 Python 中使用 bs4 运行该部分时,数据的格式也正确。我错过了什么?

您创建的 writer 实例需要一个可迭代的 writerows 方法。您正在向它传递一个字符串(其中可能包含 kommas,但这不是 csv.writer 将查看的内容:它将在每 2 个可迭代项之间添加 kommas(或您在其构造中指定的任何分隔符)。 Python 字符串是可迭代的(每个字符),因此writer.writerows("some_string") 不会导致错误。但你很可能想要这个:

for text in (all_jobs):
    t = [x.strip() for x in text.find_all(text=True)]
    jobs.append(t)

作为对 cme​​ts 的跟进: 您需要根据从 1, 2, 3 Next >> 检索到的新 url 更新 soup(它位于具有特定 iddiv 容器中,只需 BeautifulSoup 即可轻松提取)。下面的代码是一个相当基本的示例,显示了这是如何完成的。提取您认为相关的内容是由您自己的抓取代码完成的,您必须按照示例中的说明进行添加。

#Python3.x
import urllib
from bs4 import BeautifulSoup

url = 'http://www.indeed.com/cmp/Wesley-Medical-Center/reviews'
base_url_parts = urllib.parse.urlparse(url)
while True:
    raw_html = urllib.request.urlopen(url).read()
    soup = BeautifulSoup(raw_html)
    # scrape the page for the desired info 
    # ...

    last_link = soup.find('div', id='company_reviews_pagination').find_all('a')[-1]
    if last_link.text.startswith('Next'):
        next_url_parts = urllib.parse.urlparse(last_link['href'])
        url = urllib.parse.urlunparse((base_url_parts.scheme, base_url_parts.netloc,
            next_url_parts.path, next_url_parts.params, next_url_parts.query,
            next_url_parts.fragment))
        print(url)
    else:
        break

【讨论】:

  • 谢谢,我会尝试并告诉您是否可行(并尽快接受您的回答)。抱歉耽搁了 - 一直在旅行。
  • 好吧,我可能比较迟钝,但是即使我在点击每个新页面后尝试重新启动汤变量,代码也不起作用。这是我要抓取的页面:indeed.com/cmp/Wesley-Medical-Center/reviews(这是初始页面;程序单击“下一页”直到到达最后一页)。任何人都可以帮忙吗? TIA!
  • @anne_t,现在我看到了 URL,你是想抓取隐藏在“1、2、3、下一个”后面的链接,还是要“评论这家公司”。我的猜测是前者,在这种情况下,您会对soup.find('div', id='company_reviews_pagination').find_all('a')[-1]['href'] 而不是上面写的element=wait.until(... 感兴趣。但请注意:这将返回一个相对超引用:您仍然需要添加方案和网络位置(http://www.indeed.com)。
  • 谢谢!只是为了确保:我想抓取三页的文本:初始一页 (indeed.com/cmp/Wesley-Medical-Center/reviews),第二页的文本,依此类推。我让程序点击“下一步”好吧,但是汤的重新初始化(以及将抓取结果附加到 csv 文件)给我带来了麻烦。
  • @anne_t 我添加了一个更详细的示例,显示如何更新soup。将抓取结果附加到 csv 文件是相当有据可查的,我想你会管理的。祝你好运!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-16
  • 2018-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多