我是StackOverflow的新手。如果帖子结构不好,请提前道歉。
我一直在学习用python抓取网页,作为我开发的一个业余项目的一部分,我尝试抓取Google Jobs的网页,并提取特定的数据存储在Pandas数据框中,我在python上使用 selenium 来实现这一点。
因此,我面临的主要挑战是找到一种方法,从搜索查询(url = Google Jobs)获得的网站上抓取所有的工作记录。这很困难,因为Google Jobs是动态加载的,即无限滚动,页面最初在侧面板上只加载10个结果。向下滚动时,每次滚动只会加载10个结果。
Website preview
我使用了selenium来帮助我完成这个任务,我想我可以通过指示selenium滚动到侧面板中与最后一个作业条目关联的列表元素(〈\li〉),并运行一个for循环来重复它,直到所有结果都加载到页面上,从而自动化滚动。
然后我只需要提取列表元素并将它们的文本存储到数据框中。
问题是每个职务条目都有3 - 6行文本,每行表示一些属性,如职务、公司名称或位置等,每个职务条目的行数不同,导致某些条目的行数比其他条目多。
Different number of lines for each job entry
因此,当我使用'\n'作为分隔符将文本拆分为python列表时,会导致列表长度不同,当我使用pd.DataFrame(list)生成 Dataframe 时,这就成了一个问题,会导致字段顺序混乱的记录。
Different Length Lists 😓
下面是我编写的代码:
#imports
import pandas as pd
import numpy as np
from serpapi import GoogleSearch
import requests
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
#using selenium to launch and scroll through the Google Jobs page
url = "https://www.google.com/search?q=google+jobs+data+analyst&oq=google+jobs+data+analyst&aqs=chrome..69i57j69i59j0i512j0i22i30i625l4j69i60.4543j0j7&sourceid=chrome&ie=UTF-8&ibp=htl;jobs&sa=X&ved=2ahUKEwjXsv-_iZP9AhVPRmwGHX5xDEsQutcGKAF6BAgPEAU&sxsrf=AJOqlzWGHNISzgpAUCZBmQA1mWXXt3I7gA:1676311105893#htivrt=jobs&htidocid=GS94rKdYQqQAAAAAAAAAAA%3D%3D&fpstate=tldetail"
driver = webdriver.Chrome()
driver.get(url)
joblist =[]
#pointing to the html element to scroll to
elementxpath = '//*[@id="immersive_desktop_root"]/div/div[3]/div[1]/div[1]/div[3]/ul/li[10]'
element = driver.find_element(By.XPATH,elementxpath)
driver.execute_script('arguments[0].scrollIntoView(true)',element)
datas = driver.find_elements(By.XPATH,'//*
#capturing all the job list objects in the first page
[@id="immersive_desktop_root"]/div/div[3]/div[1]/div[1]/div[3]/ul/li')
joblist.append([da.text for da in datas])
#adding 3s delay for website to load after scrolling before executing code
time.sleep(3)
#capturing all the job list objects in the second set of 10 results loaded after 1st scroll down
elementxpath = '//*[@id="VoQFxe"]/div/div/ul/li[10]'
element = driver.find_element(By.XPATH,elementxpath)
driver.execute_script('arguments[0].scrollIntoView(true)',element)
datas = driver.find_elements(By.XPATH,'//*[@id="VoQFxe"]/div/div/ul/li')
joblist.append([da.text for da in datas])
x=2
time.sleep(3)
#using a while loop to scroll and capture for the remaining scroll downs as element xpath is in iterable format unlike th previous 2 xpaths
while True:
elementxpath = '//*[@id="VoQFxe"]/div['+str(1*x)+']/div/ul/li[10]'
element = driver.find_element(By.XPATH,elementxpath)
driver.execute_script('arguments[0].scrollIntoView(true)',element)
x+=1
time.sleep(3)
datas = driver.find_elements(By.XPATH,'//*[@id="VoQFxe"]/div['+str(1*x)+']/div/ul/li')
joblist.append([da.text for da in datas])
if x>1000:
break
else:
continue
#unpacking and cleaning captured values from joblist to a newlist of lists in the desired format for creating a dataframe
jlist = []
for n in joblist:
for a in range(0,len(n)-1):
if n[a]!='':
jlist.append(n[a].split('\n'))
jobdf = pd.DataFrame(jlist)
jobdf.columns = ['Logo','Role', 'Company', 'Source','Posted','Full / Part Time', 'Waste']
jobdf
这是输出 Dataframe :
Jumbled mess 😶
文化的男人和女人们,我恳求你们的帮助,以获得一个有意义的有序数据框。谢谢!
1条答案
按热度按时间kpbwa7wx1#
通常你只能在简单的情况下使用
.split('\n')
,但在这种情况下是一个坏主意,一个更好的实践是为你想要抓取的每个元素使用一个唯一的xpath,一个用于logo,一个用于role,等等。另一个好的实践是在开始时初始化字典,为每个要抓取的元素使用一个键,然后在循环作业时追加数据。
下面的代码就是这样做的,它没有优化速度,实际上它滚动到每个作业并抓取它,而最好的方法是抓取所有显示的作业的数据,然后滚动到底部,然后抓取所有新的作业并再次滚动,依此类推。
然后通过运行
pd.DataFrame(data)
,您会得到如下所示的结果如图所示,“已发布”列中的一些值应该放在“全职/兼职”列中。这是因为有些工作没有发布时间的信息。我还注意到有些工作不仅有“已发布”和“全职/兼职”数据,还有“工资”。因此,您应该调整代码以考虑到这些事实。这并不容易,因为HTML对象没有针对每个元素的特定类,所以我认为您必须利用此图像中显示的svg符号(时钟、袋子和钞票
更新
我试着使用svg路径正确地刮取“已发布”、“全职/兼职”和“工资”,效果很好!以下是路径
用新路径替换旧路径,它将按预期工作,如下图所示