爬虫案例
全网搜索–百度
1. 确定客户需求:
爬取百度搜索有关钢结构工程的公司的联系人和联系方式并保存到csv格式
2. 选择技术路线:
因为百度的反爬机制,爬取的内容全是js源代码,意思就是百度的动态数据都是js渲染出来的,通过requests爬虫则会非常复杂。
因此选用selenium作为主要的爬取工具。
3. 爬取步骤:
1. 登录百度url https://www.baidu.com 输入钢结构工程,搜索
2. 用selenium定位到每个搜索结果并提取对应的url
3. 翻页,再一次第二步操作
4. 获得的url是公司的官网
技巧
技巧一:
selenium 定位获取属性值
browser.find_element_by_xpath(’…’).get_attribute(‘TagName’)
selenium 定位获取文本
browser.find_element_by_xpath(’…’).text
find_element_by_xpath() 和 find_elements_by_xpath()的区别:
单复数,复数(即后者)返回的是列表
技巧二
selenium 通过值搜索对应的属性
比如:打开公司网页时,因为要搜索公司的联系人和联系方式
因为联系我们的标签一般存放在a标签
代码如下:
找出所有的a标签,contact_list是个列表
regex = '联系方式.*?|联系我们.*?|联系.*?'
contact_list = browser.find_elements_by_xpath('//a')
for contact in contact_list:
通过正则表达式寻找每个a标签的文本内容是否能跟regex的内容匹配
如果能够匹配到,该标签则是目标标签
if re.findall(regex, contact.text):
pass
break
技巧三:
截取长屏
# 设置chrome开启的模式,headless就是无界面模式
# 一定要使用这个模式,不然截不了全页面,只能截到你电脑的高度
chrome_options = Options()
chrome_options.add_argument('headless')
# # 窗口最大化
browser.maximize_window()
# todo:截长图
# 接下来是全屏的关键,用js获取页面的宽高,如果有其他需要用js的部分也可以用这个方法
# width = browser.execute_script("return document.documentElement.scrollWidth")
# height = browser.execute_script("return document.documentElement.scrollHeight")
browser.set_window_size(width=1200, height=1400)
# 获取body的size
# size = browser.find_element_by_xpath('//body').size
# # 将浏览器的宽高设置成刚刚获取的宽高
# browser.set_window_size(size.get('width'), size.get('height'))
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
import time, re, os
# 实现规避检测
options = ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_experimental_option('useAutomationExtension', False)
# 设置chrome开启的模式,headless就是无界面模式
# 一定要使用这个模式,不然截不了全页面,只能截到你电脑的高度
chrome_options = Options()
chrome_options.add_argument('headless')
browser = webdriver.Chrome(executable_path='./chromedriver.exe', options=options, chrome_options=chrome_options)
browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
def get_url():
url_list = []
browser.get('https://www.baidu.com')
time.sleep(1)
browser.find_element_by_xpath('//*[@id="kw"]').send_keys('浙江钢结构工程')
browser.find_element_by_xpath('//*[@id="su"]').click()
# time.sleep(1)
# browser.execute_script('window.scrollBy(0,5000)')
time.sleep(2)
for i in range(8):
# 五页内容
div_list = browser.find_elements_by_xpath('//div[@id="content_left"]/div')
time.sleep(1)
for div in div_list:
try:
company_url = div.find_element_by_xpath('div[1]/h3/a | h3/a').get_attribute('href')
# company_name = div.find_element_by_xpath('div[1]/h3/a')
url_list.append(company_url)
print(company_url)
time.sleep(0.5)
except:
continue
browser.execute_script('window.scrollBy(0,3000)')
# 翻页
# 查看是否有上一页的标签
n_page = browser.find_elements_by_xpath('//a[@class="n"]')
# 如果只有 下一页 的标签
if len(n_page) == 1:
n_page[0].click()
else:
# 如果有 上一页 下一页的标签
n_page[1].click()
time.sleep(2)
return url_list
def down_load(url):
browser.get(url)
time.sleep(1)
regex = '联系方式.*?|联系我们.*?|联系.*?'
# 藏在a标签
contact_list = browser.find_elements_by_xpath('//a')
for contact in contact_list:
if re.findall(regex, contact.text):
# # 窗口最大化
browser.maximize_window()
# todo:截长图
# 接下来是全屏的关键,用js获取页面的宽高,如果有其他需要用js的部分也可以用这个方法
# width = browser.execute_script("return document.documentElement.scrollWidth")
# height = browser.execute_script("return document.documentElement.scrollHeight")
browser.set_window_size(width=1200, height=1400)
# # 接下来是全屏的关键,用js获取页面的宽高,如果有其他需要用js的部分也可以用这个方法
# size = browser.find_element_by_xpath('//body').size
# # 将浏览器的宽高设置成刚刚获取的宽高
# browser.set_window_size(size.get('width'), size.get('height'))
time.sleep(1)
contact.click()
time.sleep(3)
t = int(time.time())
# 寻找联系方式的位置
browser.save_screenshot(f'./浙江联系方式/{t}.png')
time.sleep(1)
break
else:
continue
""""
江苏第84个1604477033
"""
if __name__ == '__main__':
# # 窗口最大化
browser.maximize_window()
if not os.path.exists('./浙江联系方式'):
os.mkdir('./浙江联系方式')
url_list = get_url()
time.sleep(1)
for url in url_list:
try:
down_load(url)
time.sleep(1)
except:
continue