前段时间有人找我写代码爬点东西,就是爬飞猪上全国景点的当月销量、优惠价、城市这些数据,等我写好了之后,他说不要了…
没辙,只能完善一下之后写出来了。
Win10 系统下 Python3,编译器是 Pycharm。
需要安装 requests,bs4,selenium 这个第三方库,直接 pip install 就可以了。还需要配置一下 driver,我用的是谷歌浏览器,所以直接用 chromedriver,配置的方法具体看这里。
万恶之首先导包
import csv
import time
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
先建一个 csv 文件来保存数据,我不想存储到数据库,只能这样了。
# 新建一个 fliggy.csv 文件,w 表示是新创建一个文件, encoding 为 utf-8-sig,中文能正常显示,
# newline="" 不能省略,省略了之后,会换行
with open("fliggy.csv", "w", encoding='utf-8-sig', newline="") as f:
csv_write = csv.writer(f)
csv_head = ["景点", "城市", "当月销量", "优惠价", "价格"]
csv_write.writerow(csv_head)
newline="" 不能省略,一省略就会导致换行多换了一行,如下图所示
接着就是配置 chromedriver
options = Options()
# options.add_argument('--headless') # headless, 无头浏览器, 不显示用户界面
options.add_argument('--disable-gpu') # 不使用 gpu
# options.add_argument("--incognito") # 以隐身模式打开
prefs = {"profile.managed_default_content_settings.images": 2} # 不显示图片
options.add_experimental_option("prefs", prefs)
# chromedriver.exe 的路径
driver_path = "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"
driver = webdriver.Chrome(executable_path=driver_path, options=options)
配置好之后就是开始爬,这里先用广州进行测试,所以 url 是广州的
driver.get(url) 的意思是 chromedriver 去访问这个 url。
url = 'http://s.fliggy.com/scenic/list.htm?q=广州'
driver.get(url)
print(url)
try:
# 获取页数
next_num = driver.find_element_by_xpath("//a[@class='pi-pagination-num'][3]").text
print(next_num)
except Exception as e:
# 处理只有一页的情况
next_num = 1
print(e)
next_num 是 一共有多少页,这个是用 xpath 来定位的,//a[@class='pi-pagination-num'][3]
, class 名为 pi-pagination-num 的 第 3 个 a 标签就是页数所在的地方。
next_num=driver.find_element_by_xpath("//a[@class='pi-pagination-num'][3]").text
就是把页数对应的文字获取到。
还记得 next_num 吗,它是总页数,所以我们需要一个 for 循环,一页一页去获取数据。
range(0, int(next_num)),从 0 开始到 总页数。Python 中,range(0, 10)的意思是从0 到 9 开始计数,计到 10 结束,但不包括 10。
for i in range(0, int(next_num)):
links = driver.find_elements_by_xpath("//a[@class='pi-btn pi-btn-primary']")
for link in links:
try:
print(link.get_attribute("href"))
res = requests.get(link.get_attribute("href"), timeout=10)
# print(res.text)
soup = BeautifulSoup(res.text, 'lxml')
name = soup.find('h3', {'class': 'scenic-tit'}).get_text().strip()
city = soup.find('span', {'class': 'scenic-subtit'}).get_text().strip()
sell_count = soup.find('dl', {'class': 'sell-count'}).find('dd').find('em').get_text().strip()
scenic_price = soup.find('span', {'class': 'pi-price-lgt'}).get_text().strip()
price = soup.find('div', {'class': 'right-area'}).find('span', {'class': 'pi-price'}).get_text().strip()
row = [name, city, sell_count, scenic_price, price]
# encoding 为 utf-8-sig, 中文能正常显示, 不信的话, 换成 utf-8试试
out = open("fliggy.csv", "a+", encoding='utf-8-sig', newline="")
csv_writer = csv.writer(out, dialect="excel")
csv_writer.writerow(row)
out.close()
except Exception as e:
print(e)
try:
# 点击下一页
driver.find_element_by_class_name('pi-pagination-next').click()
except Exception as e:
print(e)
# 休息 3 秒接着干
time.sleep(3)
# 搞定收工,退出浏览器
driver.quit()
links=driver.find_elements_by_xpath("//a[@class='pi-btn pi-btn-primary']")
是找到网页上所有的 class 属性为 pi-btn pi-btn-primary 的 a 标签。
driver.find_element_by_xpath是找一个,driver.find_elements_by_xpath找所有的,区别就在于 element 后面加没加一个 s。
得到的 links 是一个列表,需要一个一个获取需要的 href 属性,因为这个属性里面的就是景点的链接。
res=requests.get(link.get_attribute("href"), timeout=10)
的意思就是用 requests 去请求获取到的链接。
soup=BeautifulSoup(res.text, 'lxml')
,res.text 就是获取到的网页源码。用 BeautifulSoup 使用 lxml 解析器解析一下网页源码。(可以把 soup 打印出来看一下)
name 是景点名,city 是景点所在的城市,sell_count 是当月销量,scenic_price 是优惠价,price 是价格。
这里以 sell_count 来讲解一下代码,sell_count=soup.find('dl', {'class': 'sell-count'}).find('dd').find('em').get_text().strip()
, 在解析过的网页源码中,也就是 soup 中找到 class 属性为 sell-count 的 dl 标签,然后在 dl 标签里面找到 dd 标签,接着找到 em 标签。
.get_text() 是获取到里面的文字,.strip() 是去掉空格(以防万一)
别的字段都类似 sell_count 这样获取。
把数据获取到之后肯定就是保存下来,row 里面就是需要保存的数据。
以追加的形式打开 fliggy.csv,写入数据,然后 out.close()
关闭 fliggy.csv。
row = [name, city, sell_count, scenic_price, price]
# encoding 为 utf-8-sig, 中文能正常显示, 不信的话, 换成 utf-8试试
out = open("fliggy.csv", "a+", encoding='utf-8-sig', newline="")
csv_writer = csv.writer(out, dialect="excel")
csv_writer.writerow(row)
out.close()
driver.find_element_by_class_name('pi-pagination-next').click()
, 这个就是点击下一页,前面那一堆是定位到下一页,.click() 就是点击。
最终爬下来的就是下面这样,
链接是 http://s.fliggy.com/scenic/list.htm?q=广州 就是爬飞猪上广州的景点;把广州改成广东就是爬广东的;改成中国,那就是爬飞猪上全国的景点。
文章还是得多写,好久没写了,居然没感觉了。
本来是懒得写的,但是学 SEO,老师布置了个作业,要露出个外链(lbjheiheihei.xyz),只能不要脸的来写篇文章了,点击阅读原文就能跳转到了~
相关文章:
题图:Photo by Pierre Gillier on Unsplash