文章目录
- 前言
- 一、爬虫是什么?
- 二、爬虫实战案例
-
- 1.引入库
- 2.请求网页处理
- 3.生成访问链接
- 4.读入数据到mongodb
- 5.获得数据
- 6.加入多线程
- 总结
前言
在想获取网站的一些数据时,能过人工手动复制和粘贴,这样的效是不非常低的,数量少的时候可能觉得什么事,当数量多起来的时候就会显得很无力,因此爬虫就被按排上场了,本文就介绍了爬虫学习的基础内容。
一、爬虫是什么?
网络爬虫,又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者,是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本,另外一些不常使用的名字还有ipipgo、自动索引、模拟程序或者蠕虫。
二、爬虫实战案例
1.引入库
先入引一些接下来要用的库
代码如下(示例):
# requests 用来爬取页面 import requests # logging 用来输出信息 import logging # re 用来实现正则表达式解析 import re # pymongo 用来链接mongodb数据库的 import pymongo # 随机 import random from lxml import etree # urljoin 用来做 URL 的拼接 from urllib.parse import urljoin # 多线程的引入 import multiprocessing # pymongo有自带的连接池和自动重连机制,但是仍需要捕捉AutoReconnect异常并重新发起请求。 from pymongo.errors import AutoReconnect from retry import retry # 随机获取 UserAgent from fake_useragent import UserAgent import time
2.请求网页处理
scrape_page 方法是模仿浏览器发送请求用判断请求网页是否成功,以及出现异常的处理
代码如下(示例):
# 开始时间 start = time.time()
''' 如果没有为根日志程序定义处理程序,debug()、info()、warning()、error()和 critical() 函数将自动调用 basicConfig()。
level 将根记录器级别设置为指定的级别。默认生成的 root logger 的 level 是 logging.WARNING,低于该级别的就不输出了。级别排序:CRITICAL > ERROR > WARNING > INFO > DEBUG。(如果需要显示所有级别的内容,可将 level=logging.NOTSET)
format 为处理程序使用指定的格式字符串。 指定输出格式 ''' logging.basicConfig(level=logging.INFO, format='%(asctime)s – %(levelname)s: %(message)s')
# 写入请求头 headers = { 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'max-age=0', 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'document', 'sec-fetch-mode': 'navigate', 'sec-fetch-user': '?1', 'upgrade-insecure-requests': '1', 'User-Agent': UserAgent().chrome }
# 代理IP列表 Proxies = [ {"http": "http://3.221.105.1:80"}, {"http": "http://3.221.105.1:80"}, {"http": "http://3.221.105.1:80"}, ]
def scrape_page(url):
logging.info('scraping %s (···)', url) try: # 向url对应的服务器发送相应的get请求,获得对应的相应 。 response = requests.get( url, proxies=random.choice(Proxies), headers=headers) # 如果响应码为200则返回网页源码 if response.status_code == 200: return response.text # 如果不是200就在日志里打印出响应码和链接 logging.error('get invalid status code %s while scraping %s', response.status_code, url) # requests 的异常处理 except requests.RequestException: # exc_info为布尔值,如果该参数的值为True时,则会将异常信息添加到日志消息中;如果没有则会将None添加到日志信息中。 logging.error('error occurred while scraping %s', url, exc_info=True)
3.生成访问链接
scrape_index 方法是将生成的 url 全写入生成器中便于下次二次使用
代码如下(示例):
# 要爬取的网站链接 TSY_URL = 'https://www.taoshouyou.com/game/zhaohuanyingxiong-24798-0-3'
GAME_NAME = '召唤英雄' # 初始化需要爬取的总页码数量 TOTAL_PAGE = 1
def scrape_index(url): html = scrape_page(url) # 获取页码数 pattern = r'<li><a>(.*?)</a></li>' TOTAL_PAGE = re.findall(pattern, html, re.S)[0] TOTAL_PAGE = TOTAL_PAGE.split('/')[1]
# 生成链接列表 for page in range(1, int(TOTAL_PAGE) + 1): # 拼接url game_url = url + '/0-0-0-0-0-1-0-0-0-' + str(page) + '?quotaid=0' yield game_url
4.读入数据到mongodb
将爬取到的数据写入到mongodb数据库中
代码如下(示例):
# 指定 mongodb 的连接IP,库名,集合 MONGO_CONNECTION_STRING = 'mongodb://192.168.27.101:27017' MONGO_DB_NAME = 'tsy' MONGO_COLLECTION_NAME = 'tsy'
client = pymongo.MongoClient(MONGO_CONNECTION_STRING) db = client['tsy'] collection = db['tsy']
''' AutoReconnect:捕捉到该错误时进行重试,这个参数可以是一个元组,里面放上多个需要重试的条件 tries:重试次数 delay:两次重试的间隔时间 ''' @retry(AutoReconnect, tries=4, delay=1) def save_data(data): """ 将数据保存到 mongodb 使用 update_one() 方法修改文档中的记录。该方法第一个参数为查询的条件,第二个参数为要修改的字段。 upsert: 是一种特殊的更新,如果没有找到符合条件的更新条件的文档,就会以这个条件和更新文档为基础创建一个新的文档;如果找到了匹配的文档,就正常更新,upsert非常方便,不必预置集合,同一套代码既能用于创建文档又可以更新文档 """ # 存在则更新,不存在则新建, collection.update_one({ # 保证 标题链接数据 是唯一的 '标题链接': data.get('标题链接') }, { '$set': data }, upsert=True)
5.获得数据
获取数据并且对数据进行简单的处理
代码如下(示例):
def parse_detail(url): html = scrape_page(url) # 格式化html selector = etree.HTML(html) house_list = selector.xpath( '//*[@id="js-b-trade-list-conlist-trade-list"]/div[@class="row b-trade-list-conlist-box"]') # 历遍每一条数据 for house in house_list: biaoti = house.xpath("h1/a/span/text()") if len(biaoti) >= 1: biaoti = biaoti[0] zhekou = house.xpath("h1/a/span[2]/text()") jiage = re.findall(r'(d+.d{2})', biaoti.strip()) dianpu = house.xpath('div[1]/dl/dd[1]/span[2]/a/text()') shangpinleixing = house.xpath('div[1]/dl/dd[2]/text()') kehuduan = house.xpath('div[1]/dl/dd[3]/text()') youxiqufu = house.xpath('div[1]/dl/dd[4]/span/text()') html_1 = house.xpath('h1/a/@href') if zhekou == [] or dianpu == [] or shangpinleixing == [] or kehuduan == [0] or youxiqufu == [0]: print("这不是我需要的") else:
zhekou = re.findall(r'd+.?d*', zhekou[0]) game_date = { '标题': biaoti.strip(), '折扣': zhekou[0], '价格': jiage[0][:–3], '店铺': dianpu[0], '商品类型': shangpinleixing[0].split(':')[1], '客户端类型': kehuduan[0].split(':')[1], '游戏区服': youxiqufu[0], # 拼接url '标题链接': urljoin('https://www.taoshouyou.com', html_1[0]), '游戏名': GAME_NAME } logging.info('get detail data %s', game_date) logging.info('saving data to mongodb') save_data(game_date) logging.info('data saved successfully')
6.加入多线程
代码如下(示例):
if __name__ == '__main__': # 引入多线程 pool = multiprocessing.Pool() detail_urls = scrape_index(TSY_URL) # map()函数。需要传递两个参数,第一个参数就是需要引用的函数,第二个参数是一个可迭代对象,它会把需要迭代的元素一个个的传入第一个参数我们的函数中。因为我们的map会自动将数据作为参数传进去
# 传入一个url列表,parse_detail方法每次只能获取一条url pool.map(parse_detail, detail_urls) # 关闭mongodb连接 client.close()
# 关闭进程池,不再接受新的进程 pool.close() # 主进程阻塞等待子进程的退出 pool.join()
# 结束时间 end = time.time() print('Cost time: ', end – start)
总结
以上就是今天要讲的内容,本文仅仅简单介绍了针对网页源码中有数据可获取的爬虫使用。
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试