- 爬虫要根据当前url地址对应的响应为准 ,当前url地址的elements的内容和url的响应不一样
Python 爬虫是一种常用的技术,用于从网站上自动获取信息。下面是一个简单的 Python 爬虫入门教程:
1. 环境准备
首先,确保你已经安装了 Python。然后,安装以下库:
pip install requests beautifulsoup4 lxml
2. 爬虫基础知识
在开始编写代码之前,了解一些基础知识:
3. 编写爬虫代码
以一个简单的例子为例,爬取百度搜索结果。
import requests
from bs4 import BeautifulSoup
def search_baidu(keyword):
url = f'https://www.baidu.com/s?wd={
keyword}'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'lxml')
results = soup.select('.result.c-container')
for result in results:
title = result.select_one('.t a')
if title:
print(title.text)
else:
print('无标题')
else:
print('请求失败')
if __name__ == '__main__':
keyword = input('请输入搜索关键词:')
search_baidu(keyword)
这个例子中,我们使用 requests 库发送 GET 请求,获取百度搜索结果页面。然后,使用 BeautifulSoup 库解析 HTML 文档,提取搜索结果。
4. 处理异常和限制
在实际爬虫中,可能会遇到各种异常和限制。例如,网络请求失败、反爬虫策略等。因此,我们需要编写代码处理这些情况。
import time
from random import randint
def search_baidu(keyword):
url = f'https://www.baidu.com/s?wd={
keyword}'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f'请求失败:{
e}')
return
soup = BeautifulSoup(response.text, 'lxml')
results = soup.select('.result.c-container')
for result in results:
title = result.select_one('.t a')
if title:
print(title.text)
else:
print('无标题')
# 休眠一段时间,避免频繁请求
time.sleep(randint(1, 5))
if __name__ == '__main__':
keyword = input('请输入搜索关键词:')
search_baidu(keyword)
在这个例子中,我们添加了 try-except 语句,捕获网络请求失败等异常。同时,我们使用 time.sleep() 函数让爬虫在每次请求后休眠一段时间,避免频繁请求。
assert response.status_code==200
https://www.abc123.com/s?wd=%E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2
"爬{}虫教程".format(1)
准备一堆的ip地址,组成ip池,随机选择一个ip来时用
如何随机选择代理ip,让使用次数较少的ip地址有更大的可能性被用到
检查ip的可用性
cookies="anonymid=j3jxk555-nrn0wh; _r01_=1; _ga=GA1.2.1274811859.1497951251; _de=BF09EE3A28DED52E6B65F6A4705D973F1383380866D39FF5; ln_uact=mr_mao_hacker@163.com; depovince=BJ; jebecookies=54f5d0fd-9299-4bb4-801c-eefa4fd3012b|||||; JSESSIONID=abcI6TfWH4N4t_aWJnvdw; ick_login=4be198ce-1f9c-4eab-971d-48abfda70a50; p=0cbee3304bce1ede82a56e901916d0949; first_login_flag=1; ln_hurl=http://hdn.xnimg.cn/photos/hdn421/20171230/1635/main_JQzq_ae7b0000a8791986.jpg; t=79bdd322e760beae79c0b511b8c92a6b9; societyguester=79bdd322e760beae79c0b511b8c92a6b9; id=327550029; xnsid=2ac9a5d8; loginfrom=syshome; ch_id=10016; wp_fold=0"
cookies = {
i.split("=")[0]:i.split("=")[1] for i in cookies.split("; ")}
[self.url_temp.format(i * 50) for i in range(1000)]
在form表单中寻找action对应的url地址
抓包,寻找登录的url地址
python setup.py install
***.whl
安装方法 pip install ***.whl
re.findall("a(.*?)b","str")
,能够返回括号中的内容,括号前后的内容起到定位和过滤的效果
原始字符串r,待匹配字符串中有反斜杠的时候,使用r能够忽视反斜杠带来的转义的效果
点号默认情况匹配不到\n
\s
能够匹配空白字符,不仅仅包含空格,还有\t|\r\n
使用xpath helper或者是chrome中的copy xpath都是从element中提取的数据,但是爬虫获取的是url对应的响应,往往和elements不一样
获取文本
a/text()
获取a下的文本a//text()
获取a下的所有标签的文本//a[text()='下一页']
选择文本为下一页三个字的a标签@符号
a/@href
//ul[@id="detail-list"]
//
li//a
表示的是li下任何一个标签lxml能够修正HTML代码,但是可能会改错了
lxml 能够接受bytes和str的字符串
提取页面数据的思路
//div[contains(@class,'i')]
准备url
发送请求,获取响应
提取数据
如果数据在当前的url地址中
如果数据不在当前的url地址中
保存
url不变,验证码不变
url不变,验证码会变
思路:对方服务器返回验证码的时候,会和每个用户的信息和验证码进行一个对应,之后,在用户发送post请求的时候,会对比post请求中法的验证码和当前用户真正的存储在服务器端的验证码是否相同
1.实例化session
2.使用seesion请求登录页面,获取验证码的地址
3.使用session请求验证码,识别
4.使用session发送post请求’
使用selenium登录,遇到验证码
获取文本和获取属性
.text
或者get_attribute
方法来去selenium获取的页面数据是浏览器中elements的内容
find_element和find_elements的区别
如果页面中含有iframe、frame,需要先调用driver.switch_to.frame的方法切换到frame中才能定位元素
selenium请求第一页的时候回等待页面加载完了之后在获取数据,但是在点击翻页之后,hi直接获取数据,此时可能会报错,因为数据还没有加载出来,需要time.sleep(3)
selenium中find_element_by_class_name智能接收一个class对应的一个值,不能传入多个
db.stu.aggregate({
$group:{
_id:"$name",counter:{
$sum:2}}})
db.stu.aggregate({
$group:{
_id:null,counter:{
$sum:1}}})
db.stu.aggregate({
$group:{
_id:"$gender",name:{
$push:"$name"}}})
db.stu.aggregate({
$group:{
_id:"$gender",name:{
$push:"$$ROOT"}}})
db.tv3.aggregate(
{
$group:{
_id:{
"country":"$country",province:"$province",userid:"$userid"}}},
{
$group:{
_id:{
country:"$_id.country",province:"$_id.province"},count:{
$sum:1}}},
{
$project:{
country:"$_id.country",province:"$_id.province",count:"$count",_id:0}}
)
db.stu.aggregate(
{
$match:{
age:{
$gt:20}}},
{
$group:{
_id:"$gender",count:{
$sum:1}}}
)
db.t2.aggregate(
{
$unwind:"$size"}
)
db.t3.aggregate(
{
$unwind:"$tags"},
{
$group:{
_id:null,count:{
$sum:1}}}
)
db.t3.aggregate(
{
$unwind:{
path:"$size",preserveNullAndEmptyArrays:true}}
)
_id
存在就报错_id
存在会更新db.test1000.update({name:"xiaowang"},{name:"xiaozhao"})
{name:"xiaozhao"}
db.test1000.update({name:"xiaohong"},{$set:{name:"xiaozhang"}})
db.test1000.update({name:"xiaozhang"},{$set:{name:"xiaohong"}},{multi:true})
{multi:true}
达到更新多条的目的db.test1000.remove({name:"xiaohong"},{justOne:true})
{justOne:true}
能达到只删除一条的效果db.collection.find({条件}).count()
db.collection.count({})
db.collection.find({条件},{name:1,_id:0})
_id
默认会显示,置为0不显示_id
之外的其他字段,如果不显示,不写,不能写为0$group
对应的字典中有几个键,结果中就有几个键_id
后面,
$age`$_id.country
{$group:{_id:{country:"$country",province:"$province"}}}
{_id:{country:"",province:""}
db.stu.find(
{$or:[{age:{$gte:20}},{hometown:{$in:["桃花岛","华⼭"]}}]}
)
#按照gender进行分组,获取不同组数据的个数和平均年龄
db.stu.aggregate(
{$group:{_id:"$gender",count:{$sum:1},avg_age:{$avg:"$age"}}},
{$project:{gender:"$_id",count:1,avg_age:"$avg_age",_id:0}}
)
# 按照hometown进行分组,获取不同组的平均年龄
db.stu.aggregate(
{$group:{_id:"$hometown",mean_age:{$avg:"$age"}}}
)
#使用$group统计整个文档
db.stu.aggregate(
{$group:{_id:null,count:{$sum:1},mean_age:{$avg:"$age"}}}
)
#选择年龄大于20的学生,观察男性和女性有多少人
db.stu.aggregate(
{$match:{$or:[{age:{$gt:20}},{hometown:{$in:["蒙古","⼤理"]}}]}},
{$group:{_id:"$gender",count:{$sum:1}}},
{$project:{_id:0,gender:"$_id",count:1}}
)
#page37页练习
db.tv3.aggregate(
{$group:{_id:{country:"$country",province:"$province",userid:"$userid"}}},
{$group:{_id:{country:"$_id.country",province:"$_id.province"},count:{$sum:1}}},
{$project:{country:"$_id.country",province:"$_id.province",count:1,_id:0}}
)
使用数据库建立关键字段(一个或者多个)建立索引进行去重
根据url地址进行去重
根据数据本省进行去重
db.tv1.aggregate(
{
$project:{
title:1,_id:0,count:"$rating.count",rate:"$rating.value",country:"$tv_category"}},
{
$match:{
rate:{
$gt:8}}},
{
$group:{
_id:"$country",count:{
$sum:1}}},
{
$project:{
_id:0,country:"$_id",count:1}}
)
scrapy
普通项目中
logger=logging.getLogger(__name__)
常见爬虫 scrapy genspider -t crawl 爬虫名 allow_domain
指定start_url,对应的响应会进过rules提取url地址
完善rules,添加Rule Rule(LinkExtractor(allow=r'/web/site0/tab5240/info\d+\.htm'), callback='parse_item'),
注意点:
def enqueue_request(self, request):
if not request.dont_filter and self.df.request_seen(request):
# dont_filter=False Ture True request指纹已经存在 #不会入队
# dont_filter=False Ture False request指纹已经存在 全新的url #会入队
# dont_filter=Ture False #会入队
self.df.log(request, self.spider)
return False
self.queue.push(request) #入队
return True
fp = hashlib.sha1()
fp.update(to_bytes(request.method)) #请求方法
fp.update(to_bytes(canonicalize_url(request.url))) #url
fp.update(request.body or b'') #请求体
return fp.hexdigest()
added = self.server.sadd(self.key, fp)
return added != 0
项目名字
项目周期
项目介绍
开发环境
使用技术
项目名字
项目周期
项目介绍
开发环境
使用技术
更多【编程技术-Python爬虫入门教程】相关视频教程:www.yxfzedu.com