使用 selenium 和 bs4 进行网页抓取
Posted
技术标签:
【中文标题】使用 selenium 和 bs4 进行网页抓取【英文标题】:Web scraping using selenium and bs4 【发布时间】:2019-02-12 12:45:24 【问题描述】:我正在尝试基于该页面的网络抓取构建数据框
https://www.schoolholidayseurope.eu/choose-a-country
html firstable 我对 selenium 说单击我选择的页面,然后我将 xpath 和标签元素放入构建标题和正文,但我没有我想要的格式我的元素是 NaN 或重复。
按照我的脚本:
def get_browser(url_selector):
"""Get the browser (a "driver")."""
#option = webdriver.ChromeOptions()
#option.add_argument(' — incognito')
path_to_chromedriver = r"C:/Users/xxxxx/Downloads/chromedriver_win32/chromedriver.exe"
browser = webdriver.Chrome(executable_path= path_to_chromedriver)
browser.get(url_selector)
""" Try with Italie"""
browser.find_element_by_xpath(italie_buton_xpath).click()
""" Raise exception : down browser if loading take more than 45sec : timer is the logo website as a flag"""
# Wait 45 seconds for page to load
timeout = 45
try:
WebDriverWait(browser, timeout).until(EC.visibility_of_element_located((By.XPATH, '//*[@id="s5_logo_wrap"]/img')))
except TimeoutException:
print("Timed out waiting for page to load")
browser.quit()
return browser
browser = get_browser(url_selector)
headers = browser.find_element_by_xpath('//*[@id="s5_component_wrap_inner"]/main/div[2]/div[2]/div[3]/table/thead').find_elements_by_tag_name('tr')
headings = [i.text.strip() for i in headers]
bs_obj = BeautifulSoup(browser.page_source, 'html.parser')
rows = bs_obj.find_all('table')[0].find('tbody').find_all('tr')[1:]
table = []
for row in rows :
line = next(td.get_text() for td in row.find_all("td"))
print(line)
table.append(line)
browser.quit()
pd.DataFrame(line, columns = headings)
返回
单列数据框,例如:
School Holiday Region Start date End date Week
0 Easter holidays 2018
1 REMARK: Small differences by region are possi...
2 Summer holiday 2018
3 REMARK: First region through to last region.
4 Christmas holiday 2018
这里有三个问题,我不希望 REMARK 行和学校假期开始日期和结束日期被视为单独的单词,并且整个数据框未拆分。
如果我拆分我的标题并排列两个不匹配的形状 由于 REMARKS 行,我的列表中有 9 个元素而不是 3 个,并且由于单词分开,我在标题中得到了 8 个元素而不是 5 个。
【问题讨论】:
你能告诉我在你的帖子中使用pd.DataFrame(line, columns = headings)
吗?或者应该是pd.DataFrame(table, columns = headings)
。
还发布您遇到的错误的完整回溯。
我没有看到那个错误,但是数据框仍然没有拆分,只有一列结构
您在哪一行出现错误?
我现在编辑没有更多错误,只是结构不理想
【参考方案1】:
你可以在主页上找到所有的链接,然后用selenium
遍历每个url:
from selenium import webdriver
from bs4 import BeautifulSoup as soup
import re, contextlib, pandas
d = webdriver.Chrome('/Users/jamespetullo/Downloads/chromedriver')
d.get('https://www.schoolholidayseurope.eu/choose-a-country')
_, *countries = [(lambda x:[x.text, x['href']])(i.find('a')) for i in soup(d.page_source, 'html.parser').find_all('li', 'class':re.compile('item\d+$'))]
@contextlib.contextmanager
def get_table(source:str):
yield [[[i.text for i in c.find_all('th')], [i.text for i in c.find_all('td')]] for c in soup(source, 'html.parser').find('table', 'class':'zebra').find_all('tr')]
results =
for country, url in countries:
d.get(f'https://www.schoolholidayseurope.euurl')
with get_table(d.page_source) as source:
results[country] = source
def clean_results(_data):
[headers, _], *data = _data
return [dict(zip(headers, i)) for _, i in data]
final_countries = a:clean_results(b) for a, b in results.items()
【讨论】:
工作得很好,谢谢,我想了解 contextlib 的一些细节?以上是关于使用 selenium 和 bs4 进行网页抓取的主要内容,如果未能解决你的问题,请参考以下文章
“AttributeError:‘str’对象没有属性‘descendants’错误,使用 bs4 和 selenium 进行自动抓取
使用 BS4 进行网页抓取 - “传递值的长度为 0,索引意味着 7”
在 Python 中使用 BS4、Selenium 抓取动态数据并避免重复