前言
“人在家中坐,课从网上来。”
这两天老师在讲网络爬虫,博主在学习的过程中也是充分的感受到了网络世界的险恶:被豆瓣网封ip了n次,被美团封ip了7次,被安居客封ip了6次。每次都是感觉写的差不多了,数据的存储也没啥问题,准备磨刀霍霍向猪羊的时候发现被封了,然后瘫在椅子上哀声长叹。 还是技术不精导致的啊,说白了就是太菜。
昨天老师给我们留下了一份作业:分别用requests 模块与selenium 模块两种办法爬取链家网中前五页的房源数据,数据中需要有每一处房源的地理位置(所处的经度与纬度)。
本篇博客主要讲解一下如何用selenium 模块获取到房源的地理位置(所处的经度与纬度)。一共有两种方式,其中一种在某种意义上来说是由错误操作导致的正解。
0.前置安装
一.Python库
①bs4 模块(洗数据,需要手动安装)
②selenium 模块(爬取数据,需要手动安装)
③re 模块(正则表达式,内置模块,无需手动安装)
④json 模块(洗数据,内置模块,无需手动安装)
二.其他
①chrome浏览器
②chromedriver(一定要和你的chrome浏览器的版本对应)
1.爬取网页源码
爬取源码的代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
browser = webdriver.Chrome(service=Service(r'F:\安装包\chromedriver_win32\chromedriver.exe'))
browser.get('https://jn.lianjia.com/zufang/JN2837118469127290880.html?nav=0&unique_id=7d5fa73c-670c-44ba-b0dd-d2b04c63d8a2zufang1642226627144')
html=browser.page_source
with open('./test.html', 'w', encoding='utf-8') as f:
f.write(html)
f.close()
browser.close()
2.分析源码,找出获取地理位置的途径
Ⅰ.正则表达式法
菜狗博主的正则表达式学的比较烂,所以可能代码看上去十分的丑并且可能会非常多余,还请多多包涵,求同存异。
大家在使用上面的代码获取到网页源码之后,在生成的html 文件里搜索关键字:g_conf.coord ,就会出现以下源码:
g_conf.coord = {
longitude: '116.935819',
latitude: '36.697197'
};
那么这串代码中的(116.935819,36.697197) 就是这处房源的地理位置了。
那现在思路就很清晰了:想个办法把这两个数从整个源码中洗出来。
代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from bs4 import BeautifulSoup
import re
browser = webdriver.Chrome(service=Service(r'F:\安装包\chromedriver_win32\chromedriver.exe'))
browser.get('https://jn.lianjia.com/zufang/JN2837118469127290880.html?nav=0&unique_id=7d5fa73c-670c-44ba-b0dd-d2b04c63d8a2zufang1642226627144')
html = browser.page_source
pattern = re.compile(r"([a-z]+: '\d+.\d+')", re.I)
list = pattern.findall(html)
print(list)
postion = "(" + re.search(r'\d+.\d+', list[0]).group(0) + " , " + re.search(r'\d+.\d+', list[1]).group(0) + ")"
print(postion)
browser.close()
Ⅱ.错误中产生的另一种正解
在合租·盛世花城 5居室 南卧网页中,房源的位置周边介绍部分用的是百度地图插件,这个插件的特点就在于当地图没有出现在你的屏幕中时,这个插件的代码就不会加载。
插件加载前网页源码部分:
插件加载后网页源码部分:
在插件生成的源码里也是有这个房源的地理位置的:
那么如果我们想办法让这个插件加载出这段代码,我们就可以直接用bs4 洗出这个div 标签的data-coord 属性,也能得到地理位置。 那么这就需要我们在爬虫中加上一段让网页下拉到地图部分的代码。
那么博主一开始也是想到了可以通过拖动滚动条来使整个页面下拉:
browser.execute_script("document.documentElement.scrollTop=2700")
但网页下拉多少距离才能正好显示出地图那一部分,这个值是不固定的(不同的房源显示的数据不同),所以上面的这行代码不能精准空降到地图部分,感兴趣的小伙伴可以尝试一下。
预期结果:不同的网页最后下拉到的位置不同。
那么有没有什么办法可以精准空降呢? 有的,我们看一下插件加载前的源码与插件加载后的源码,我们会发现无论插件是否加载,有一个标签源码是一定加载出来的:<div class="content__map"> 。那么我们就可以想办法定位到这个标签的位置,然后让页面跳转到这个位置即可。 大佬博客:https://blog.csdn.net/xhaimail/article/details/105031948
代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from bs4 import BeautifulSoup
import json
import re,time
browser = webdriver.Chrome(service=Service(r'F:\安装包\chromedriver_win32\chromedriver.exe'))
browser.get('https://jn.lianjia.com/zufang/JN2837118469127290880.html?nav=0&unique_id=7d5fa73c-670c-44ba-b0dd-d2b04c63d8a2zufang1642226627144')
target = browser.find_element("class name", 'content__map')
browser.execute_script("arguments[0].scrollIntoView();", target)
time.sleep(1)
html = browser.page_source
htmls = BeautifulSoup(html, 'lxml')
print(htmls.select('div[class="map__cur"]')[0].attrs['data-coord'])
print("(" + json.loads(htmls.select('div[class="map__cur"]')[0].attrs['data-coord'])['longitude'] + " , " +json.loads(htmls.select('div[class="map__cur"]')[0].attrs['data-coord'])['latitude'] + ")")
browser.close()
当时在写这个的时候并没有发现正则表达式法中的那段代码,所以这第二种办法也算是一个错误所产生的正解,有点歪打正着的感觉。
吾日三省吾身:日更否?刷题否?快乐否?
更新了,但不是日更;已刷;平静
路漫漫其修远兮,吾将上下而求索
|