【问题标题】:Pandas to_csv only write the data from certain pagePandas to_csv 只写入来自特定页面的数据
【发布时间】:2021-07-22 10:21:03
【问题描述】:

我尝试从tripadvisor 中抓取数据,但是从我尝试抓取的几个页面中,当我尝试将其导出到csv 时,它只显示1 行数据并给出类似这样的错误消息

AttributeError: 'NoneType' object has no attribute 'text'

这是我的代码

import requests
import pandas as pd
from requests import get
from bs4 import BeautifulSoup

URL = 'https://www.tripadvisor.com/Attraction_Review-g469404-d3780963-Reviews-oa'

for offset in range(0, 30, 10):
    
    url = URL + str(offset) + '-Double_Six_Beach-Seminyak_Kuta_District_Bali.html'
    headers = {"User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}
    
    r = requests.get(url, headers=headers)
    soup = BeautifulSoup(r.text, "html.parser")    
    
    container = soup.find_all('div', {'class':'_2rspOqPP'})
    
    for r in container:
        reviews = r.find_all('div', {'class': None})

        #the container that contains the elements that I want to scrape has no attributes and use DOM element. So I tried to access div with _2rspOqPP class first then access the div with no attributes from there

        records = []
        for review in reviews:
            user = review.find('a', {'class':'_7c6GgQ6n _37QDe3gr WullykOU _3WoyIIcL'}).text
            country = review.find('div', {'class' : 'DrjyGw-P _26S7gyB4 NGv7A1lw _2yS548m8 _2cnjB3re _1TAWSgm1 _1Z1zA2gh _2-K8UW3T _1dimhEoy'}).span.text
            date = review.find('div', {'class' : '_3JxPDYSx'}).text
            content = review.find('div', {'class' : 'DrjyGw-P _26S7gyB4 _2nPM5Opx'}).text

            records.append((user, country, date, content))
            df = pd.DataFrame(records, columns=['Name', 'Country', 'Date', 'Content'])
            df.to_csv('doublesix_.csv', index=False, encoding='utf-8')

代码更新

for r in container:
    reviews = r.find_all('div', {'class': None})
    records = []
    for review in reviews:
        try:
            user = review.find('a', {'class':'_7c6GgQ6n _37QDe3gr WullykOU _3WoyIIcL'}).text
            country = review.find('div', {'class' : 'DrjyGw-P _26S7gyB4 NGv7A1lw _2yS548m8 _2cnjB3re _1TAWSgm1 _1Z1zA2gh _2-K8UW3T _1dimhEoy'}).span.text
            date = review.find('div', {'class' : '_3JxPDYSx'}).text
            content = review.find('div', {'class' : 'DrjyGw-P _26S7gyB4 _2nPM5Opx'}).text
            
            records.append((user, country, date, content))
        except:
            pass
        

print(records)
df = pd.DataFrame(records, columns=['Name', 'Country', 'Date', 'Content'])
df.to_csv('doublesix_.csv', index=False, encoding='utf-8')

【问题讨论】:

  • 您需要附加数据并在最后写入 csv。考虑在 for 循环之前将以下行移出循环 df = pd.DataFrame(records, columns=['Name', 'Country', 'Date', 'Content']) df.to_csv('doublesix_.csv', index=False, encoding='utf-8')records = []
  • 这是问题的一部分。我认为review.find()返回None还有另一个问题,因此你不能None.text。您将需要一些异常来处理 try/except。它基本上在第一个被刮掉的页面后就死了。
  • @astrochun 我尝试添加异常处理(我更新了我的代码),它抓取所有页面但只写入最后一页的数据并在抓取的页面之间出现一些异常
  • @astrochun 哦我也想问一下,在HTML页面中只有一个带有_2rspOqPP类的div,但是我用find_all()来选择元素,会不会影响我的代码?跨度>

标签: python pandas beautifulsoup


【解决方案1】:

您应该将records 移出for loops 并取消缩进最后几行。

看这个:

import pandas as pd
import requests
from bs4 import BeautifulSoup

main_url = 'https://www.tripadvisor.com/Attraction_Review-g469404-d3780963-Reviews-oa'

country_class = "DrjyGw-P _26S7gyB4 NGv7A1lw _2yS548m8 _2cnjB3re _1TAWSgm1 _1Z1zA2gh _2-K8UW3T _1dimhEoy"
records = []

for offset in range(0, 30, 10):
    url = main_url + str(offset) + '-Double_Six_Beach-Seminyak_Kuta_District_Bali.html'
    headers = {
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
    }

    soup = BeautifulSoup(requests.get(url, headers=headers).text, "html.parser")
    container = soup.find_all('div', {'class': '_2rspOqPP'})
    for r in container:
        reviews = r.find_all('div', {'class': None})
        for review in reviews:
            try:
                user = review.find('a', {'class': '_7c6GgQ6n _37QDe3gr WullykOU _3WoyIIcL'}).text
                country = review.find('div', {'class': country_class}).span.text
                date = review.find('div', {'class': '_3JxPDYSx'}).text
                content = review.find('div', {'class': 'DrjyGw-P _26S7gyB4 _2nPM5Opx'}).text
                records.append((user, country, date, content))
            except AttributeError:
                pass

df = pd.DataFrame(records, columns=['Name', 'Country', 'Date', 'Content'])
df.to_csv('doublesix_.csv', index=False, encoding='utf-8')

.csv 文件的输出:

【讨论】:

  • 我也有一个问题,当我尝试只抓取 3-10 页时它工作正常,但是当我将页面增加到 100 页时,我收到一些类似 ConnectionError 的错误:('Connection aborted .', OSError("(10060, 'WSAETIMEDOUT')")) 你有什么修复它的建议吗?
  • 是的,用刮擦放慢速度。服务器断开连接,因为您发送的请求过多。
猜你喜欢
  • 1970-01-01
  • 2020-03-16
  • 2015-10-19
  • 1970-01-01
  • 2018-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多