python 玻璃门星星

6jjcrrmo  于 2022-12-02  发布在  Python
关注(0)|答案(1)|浏览(184)

我是新来的 selenium 。我通常刮用BeautifulSoup。我的问题是,我不能用bs 4刮玻璃门的子评级在其评论。Below is an example:
到目前为止,我已经发现了这些星星的位置,但它们的代码是相同的,无论颜色如何(即绿色或灰色)...**我需要能够识别颜色来识别评级,而不仅仅是刮星星。**下面是我的代码:

url='https://www.glassdoor.com/Reviews/Walmart-Reviews-E715_P2.htm?filter.iso3Language=eng'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
com = soup.find(class_ = "ratingNumber mr-xsm")
com1 = soup.find(class_ = "gdReview")
com1_1 = com1.find(class_ = "content")

我非常需要有人来帮助修改我的代码或张贴他或她的完整代码,如果解决方案是在代码以外的bs 4(我真的是新的 selenium ...)这里提供的解决方案Cannot scrape glassdoor rating's stars似乎不适合我。请提供帮助,因为它关系到我的论文。谢谢。

**EDIT:**有了@Driftr95提供的答案(真的非常感谢),我设法刮了一下。然而,我的最终目标是刮下这家公司的全部评论。我试着通过操纵Driftr 95的代码来做到这一点:

def extract(pg): 
headers = {'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'}
url = f'https://www.glassdoor.com/Reviews/3M-Reviews-E446_P{pg}.htm?filter.iso3Language=eng'

r = requests.get(url, headers, timeout=(3.05, 27))
soup = BeautifulSoup(r.content, 'html.parser')
return soup 

for j in range(1,21,10):
   for i in range(j+1,j+11,1): #3M: 4251 reviews
      soup = extract( f'https://www.glassdoor.com/Reviews/3M-Reviews-E446_P{i}.htm?filter.iso3Language=eng')
      print(f' page {i}')
      for r in soup.select('li[id^="empReview_"]'):
          rDet = {'reviewId': r.get('id')}
          for sr in r.select(subRatSel):
              k = sr.select_one('div:first-of-type').get_text(' ').strip()
              sval = getDECstars(sr.select_one('div:nth-of-type(2)'), soup)
              rDet[f'[rating] {k}'] = sval

          for k, sel in refDict.items():
              sval = r.select_one(sel)
              if sval: sval = sval.get_text(' ').strip()
              rDet[k] = sval

          empRevs.append(rDet)

我面临的新问题

1.我的for循环的结果是评论的顺序与网站显示的不一样。而且,我的for循环的结果往往有重复的评论。在这个例子中,我收集了200条评论,结果只有170条唯一的评论,而网站没有重复的评论(即正好200条唯一的评论)。
1.我需要3 M的评论总数(即,4251评论)或总页数(即,这一个我不知道如何做,但我观察到,每个页面包含约10评论,所以最多应该是426页).有一个简单的方法来做它与我和@Driftr95的代码的组合?
非常感谢您在评论部分提供的所有帮助。

qvtsj1bj

qvtsj1bj1#

对于获得星星细分(似乎没有数字显示或 meta值),我不认为有任何非常简单和直接的短方法,因为它是by css in a style tag connected by a class of the container element
您可以使用soup.select('style:-soup-contains(".css-1nuumx7")') [css-1nuumx7部分特定于上面提到的rating],但是:-soup-contains需要html5lib解析器,可能会有点慢,所以最好找出style标签的data-emotion-css属性:

def getDECstars(starCont, mSoup, outOf=5,  isv=False):
    classList = starCont.get('class', [])
    if type(classList) != list: classList = [classList]
    classList = [str(c) for c in classList if str(c).startswith('css-')] 
    if not classList: 
        if isv: print('Stars container has no "css-" class')
        return None
    
    demc = classList[0].replace('css-', '', 1)
    demc_sel = f'style[data-emotion-css="{demc}"]'
    cssStyle = soup.select_one(demc_sel)
    if not cssStyle:
        if isv: print(f'Nothing found with selector {demc_sel}')
        return None
    
    cssStyle = cssStyle.get_text()
    errMsg = ''
    if '90deg,#0caa41 ' not in cssStyle: errMsg += 'No #0caa41'
    if '%' not in cssStyle.split('90deg,#0caa41 ', 1)[-1][:20]: 
        errMsg += ' No %'
    if not errMsg:
        rPerc = cssStyle.split('90deg,#0caa41 ', 1)[-1]
        rPerc = rPerc.split('%')[0]
        try:  
            rPerc = float(rPerc)
            if 0 <= rPerc <= 100:
                if type(outOf) == int and outOf > 0: rPerc = (rPerc/100)*outOf
                return float(f'{float(rPerc):.3}')
            errMsg = f'{demc_sel} --> "{rPerc}" is out of range'
        except: errMsg = f'{demc_sel} --> cannot convert to float "{rPerc}"' 
    if isv: print(f'{demc_sel} --> unexpected format {errMsg}')
    return None

或者,如果您不太关心为什么缺少评级:

def getDECstars(starCont, mSoup, outOf=5, isv=False):
    try:
        demc = [c for c in starCont.get('class', []) if c[:4]=='css-'][0].replace('css-', '', 1)
        demc_sel = f'style[data-emotion-css="{demc}"]'
        rPerc = float(soup.select_one(demc_sel).get_text().split('90deg,#0caa41 ', 1)[1].split('%')[0])
        return float(f'{(rPerc/100)*outOf if type(outOf) == int and outOf > 0 else rPerc:.3}')
    except: return None

下面是一个如何使用它的示例:

pcCon = 'div.px-std:has(h2 > a.reviewLink) + div.px-std'
pcDiv = f'{pcCon} div.v2__EIReviewDetailsV2__fullWidth'
refDict = {
    'rating_num': 'span.ratingNumber',
    'emp_status': 'div:has(> div > span.ratingNumber) + span',
    'header': 'h2 > a.reviewLink',
    'subheader': 'h2:has(> a.reviewLink) + span',
    'pros': f'{pcDiv}:first-of-type > p.pb',
    'cons': f'{pcDiv}:nth-of-type(2) > p.pb'
}

subRatSel = 'div:has(> .ratingNumber) ~ aside ul > li:has(div ~ div)'
empRevs = []
for r in soup.select('li[id^="empReview_"]'):
    rDet = {'reviewId': r.get('id')}
    for sr in r.select(subRatSel):
        k = sr.select_one('div:first-of-type').get_text(' ').strip()
        sval = getDECstars(sr.select_one('div:nth-of-type(2)'), soup)
        rDet[f'[rating] {k}'] = sval
    
    for k, sel in refDict.items():
        sval = r.select_one(sel)
        if sval: sval = sval.get_text(' ').strip()
        rDet[k] = sval
    
    empRevs.append(rDet)

如果将empRevs视为表格:
| 审查ID| [rating]工作/生活平衡|[评分]文化与价值观|[rating]多元化与包容性|[rating]职业机会|[rating]薪酬和福利|[评级]高级管理层|额定值|员工状态|集管|副标题|赞成|康|
| - -|- -|- -|- -|- -|- -|- -|- -|- -|- -|- -|- -|- -|
| 员工审核_71400593|五个|四个|四个|四个|五个|三个|三个||薪水很高,但环境有点讨厌|2022年11月26日-宾夕法尼亚州本萨莱姆销售助理/出纳|- 沃尔玛的公平薪酬政策是...|- 有些地方不会建立emp...|
| 员工审核_70963705|三个|三个|2个|2个|2个|2个|2个|前员工|沃尔玛员工接受培训后被扔进狼群|2022年11月10日-数据输入|在休息时吃点零食是一件很棒的事情。|我在沃尔玛工作了一个非常...|
| 员工审核_71415031|四个|四个|四个|四个|四个|四个|五个|当前员工,1年以上|工作|2022年11月27日-佐治亚州斯普林菲尔德仓库助理|那里的钱在...|有时候压力会很大...|
| 员工审核_69136451|楠|楠|楠|楠|楠|楠|四个|当前员工|沃尔玛|2022年9月16日-销售助理/出纳|我是一个有经验的工人。我...|在我看来,我相信W...|
| 员工审核_71398525|四个|三个|四个|三个|四个|三个|四个|当前员工|很大程度上取决于您的团队|2022年11月26日-个人数字购物者|我有一个很好的...|一般情况下,各部门都有自己的职责。|
| 员工审核_71227029|一个|一个|一个|一个|三个|一个|一个|前员工,未满1年|经理们被当作奴隶对待。|2022年11月19日-亚利桑那州棉白杨汽车护理中心经理(ACCM)|如果你喜欢和...|你只能在你的...|
| 员工审核_71329467|一个|三个|三个|三个|四个|一个|一个|当前员工,3年以上|没有其他值|2022年11月23日-德克萨斯州休斯顿通用汽车公司教练|与其他零售商相比,支付...|沃尔玛不是一个坏公司t...|
| 员工审核_71512609|五个|五个|五个|五个|五个|五个|五个|前员工|沃尔玛午夜储料器|2022年11月30日-午夜斯托克在泰勒,密歇根州|2个带薪15分钟休息和1小时的休息时间。|说真的我什么都不能...|
| 员工审核_70585957|三个|四个|四个|四个|四个|四个|四个|前员工|大量机会|2022年10月28日-人力资源人员负责人|有很多机会如果...|和任何工作一样,管理是...|
| 员工审核_71519435|三个|四个|四个|五个|四个|四个|五个|当前员工,3年以上|大量的工作,但值得|2022年11月30日-以人为本|我喜欢让律师们活在...|有时候一个压倒性的爱...|
上面那张table的减价单上印着Pandas:

erdf = pandas.DataFrame(empRevs).set_index('reviewId')
erdf['pros'] = [p[:30] + '...' if len(p) > 33 else p for p in erdf['pros']]
erdf['cons'] = [p[:30] + '...' if len(p) > 33 else p for p in erdf['cons']]
print(erdf.to_markdown())

相关问题